This is the mail archive of the binutils-cvs@sourceware.org mailing list for the binutils project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

[binutils-gdb] New ARC implementation.


https://sourceware.org/git/gitweb.cgi?p=binutils-gdb.git;h=886a250647ac0c608f20a7007fc2167a70f64e20

commit 886a250647ac0c608f20a7007fc2167a70f64e20
Author: Nick Clifton <nickc@redhat.com>
Date:   Wed Oct 7 14:20:19 2015 +0100

    New ARC implementation.
    
    bfd	* archures.c: Remove support for older ARC. Added support for new
    	ARC cpus (ARC600, ARC601, ARC700, ARCV2).
    	* bfd-in2.h: Likewise.
    	* config.bfd: Likewise.
    	* cpu-arc.c: Likewise.
    	* elf32-arc.c: Totally changed file with a refactored
    	inplementation of the ARC port.
    	* libbfd.h: Added ARC specific relocation types.
    	* reloc.c: Likewise.
    
    gas     * config/tc-arc.c: Revamped file for ARC support.
            * config/tc-arc.h: Likewise.
            * doc/as.texinfo: Add new ARC options.
            * doc/c-arc.texi: Likewise.
    
    ld	* configure.tgt: Added target arc-*-elf* and arc*-*-linux-uclibc*.
    	* emulparams/arcebelf_prof.sh: New file
    	* emulparams/arcebelf.sh: Likewise.
    	* emulparams/arceblinux_prof.sh: Likewise.
    	* emulparams/arceblinux.sh: Likewise.
    	* emulparams/arcelf_prof.sh: Likewise.
    	* emulparams/arcelf.sh: Likewise.
    	* emulparams/arclinux_prof.sh: Likewise.
    	* emulparams/arclinux.sh: Likewise.
    	* emulparams/arcv2elfx.sh: Likewise.
    	* emulparams/arcv2elf.sh: Likewise.
    	* emultempl/arclinux.em: Likewise.
    	* scripttempl/arclinux.sc: Likewise.
    	* scripttempl/elfarc.sc: Likewise.
    	* scripttempl/elfarcv2.sc: Likewise
    	* Makefile.am: Add new ARC emulations.
    	* Makefile.in: Regenerate.
    	* NEWS: Mention the new feature.
    
    opcodes * arc-dis.c: Revamped file for ARC support
    	* arc-dis.h: Likewise.
    	* arc-ext.c: Likewise.
    	* arc-ext.h: Likewise.
    	* arc-opc.c: Likewise.
    	* arc-fxi.h: New file.
    	* arc-regs.h: Likewise.
    	* arc-tbl.h: Likewise.
    
    binutils * readelf.c (get_machine_name): Remove A5 reference. Add ARCompact
    	and ARCv2.
    	(get_machine_flags): Handle EM_ARCV2 and EM_ARCOMPACT.
    	(guess_is_rela): Likewise.
    	(dump_relocations): Likewise.
    	(is_32bit_abs_reloc): Likewise.
    	(is_16bit_abs_reloc): Likewise.
    	(is_none_reloc): Likewise.
    	* NEWS: Mention the new feature.
    
    include	* dis-asm.h (arc_get_disassembler): Correct declaration.
    	* arc-reloc.def: Macro file with definition of all relocation
    	types.
    	* arc.h: Changed macros for the newly supported ARC cpus.  Altered
    	enum defining the supported relocations.
    	* common.h: Changed EM_ARC_A5 definition to EM_ARC_COMPACT. Added
    	macro for EM_ARC_COMPACT2.
            * arc-func.h: New file.
            * arc.h: Likewise.

Diff:
---
 bfd/ChangeLog                               |    12 +
 bfd/archures.c                              |    10 +-
 bfd/bfd-in2.h                               |    86 +-
 bfd/config.bfd                              |     3 +-
 bfd/cpu-arc.c                               |    18 +-
 bfd/elf32-arc.c                             |  1734 ++-
 bfd/elfxx-sparc.c                           |     6 +-
 bfd/libbfd.h                                |    67 +-
 bfd/reloc.c                                 |   141 +-
 binutils/ChangeLog                          |    13 +
 binutils/NEWS                               |     2 +
 binutils/readelf.c                          |    75 +-
 binutils/testsuite/binutils-all/objdump.exp |     2 +-
 gas/ChangeLog                               |     7 +
 gas/NEWS                                    |     3 +
 gas/config/tc-arc.c                         |  4396 ++++---
 gas/config/tc-arc.h                         |   173 +-
 gas/configure.tgt                           |    10 +-
 gas/doc/as.texinfo                          |    12 +-
 gas/doc/c-arc.texi                          |   529 +-
 gas/testsuite/ChangeLog                     |    77 +
 gas/testsuite/gas/all/gas.exp               |     2 +-
 gas/testsuite/gas/arc/adc.d                 |   140 +-
 gas/testsuite/gas/arc/adc.s                 |    69 +-
 gas/testsuite/gas/arc/add.d                 |   140 +-
 gas/testsuite/gas/arc/add.s                 |    69 +-
 gas/testsuite/gas/arc/alias.d               |    68 -
 gas/testsuite/gas/arc/alias.s               |    76 -
 gas/testsuite/gas/arc/and.d                 |   140 +-
 gas/testsuite/gas/arc/and.s                 |    69 +-
 gas/testsuite/gas/arc/arc.exp               |    50 +-
 gas/testsuite/gas/arc/asl.d                 |   123 +-
 gas/testsuite/gas/arc/asl.s                 |   117 +-
 gas/testsuite/gas/arc/asr.d                 |   106 +-
 gas/testsuite/gas/arc/asr.s                 |    97 +-
 gas/testsuite/gas/arc/b.d                   |   112 +-
 gas/testsuite/gas/arc/b.s                   |    10 +-
 gas/testsuite/gas/arc/bic.d                 |   140 +-
 gas/testsuite/gas/arc/bic.s                 |    69 +-
 gas/testsuite/gas/arc/bl.d                  |   114 +-
 gas/testsuite/gas/arc/bl.s                  |    10 +-
 gas/testsuite/gas/arc/branch.d              |    45 -
 gas/testsuite/gas/arc/branch.s              |    47 -
 gas/testsuite/gas/arc/brk.d                 |    14 +-
 gas/testsuite/gas/arc/brk.s                 |     4 +-
 gas/testsuite/gas/arc/extb.d                |    67 +-
 gas/testsuite/gas/arc/extb.s                |    17 -
 gas/testsuite/gas/arc/extensions.d          |     5 +-
 gas/testsuite/gas/arc/extw.d                |    67 +-
 gas/testsuite/gas/arc/extw.s                |    17 -
 gas/testsuite/gas/arc/flag.d                |    58 +-
 gas/testsuite/gas/arc/insn3.d               |    44 -
 gas/testsuite/gas/arc/insn3.s               |    52 -
 gas/testsuite/gas/arc/j.d                   |   186 +-
 gas/testsuite/gas/arc/j.s                   |     4 +-
 gas/testsuite/gas/arc/jl.d                  |    31 +-
 gas/testsuite/gas/arc/jl.s                  |     5 +-
 gas/testsuite/gas/arc/ld.d                  |    24 +-
 gas/testsuite/gas/arc/ld.s                  |     6 +-
 gas/testsuite/gas/arc/ld2.d                 |    32 +-
 gas/testsuite/gas/arc/ld2.s                 |     2 +-
 gas/testsuite/gas/arc/lp.d                  |   105 +-
 gas/testsuite/gas/arc/lp.s                  |    11 +-
 gas/testsuite/gas/arc/lsr.d                 |   106 +-
 gas/testsuite/gas/arc/lsr.s                 |    97 +-
 gas/testsuite/gas/arc/math.d                |    78 -
 gas/testsuite/gas/arc/math.s                |    89 -
 gas/testsuite/gas/arc/mov.d                 |   118 +-
 gas/testsuite/gas/arc/mov.s                 |    56 +-
 gas/testsuite/gas/arc/nop.d                 |    10 +-
 gas/testsuite/gas/arc/nop.s                 |     2 +-
 gas/testsuite/gas/arc/or.d                  |   140 +-
 gas/testsuite/gas/arc/or.s                  |    69 +-
 gas/testsuite/gas/arc/rlc.d                 |    84 +-
 gas/testsuite/gas/arc/rlc.s                 |    37 -
 gas/testsuite/gas/arc/ror.d                 |   106 +-
 gas/testsuite/gas/arc/ror.s                 |    97 +-
 gas/testsuite/gas/arc/rrc.d                 |    67 +-
 gas/testsuite/gas/arc/rrc.s                 |    17 -
 gas/testsuite/gas/arc/sbc.d                 |   140 +-
 gas/testsuite/gas/arc/sbc.s                 |    69 +-
 gas/testsuite/gas/arc/sexb.d                |    67 +-
 gas/testsuite/gas/arc/sexb.s                |    17 -
 gas/testsuite/gas/arc/sexw.d                |    67 +-
 gas/testsuite/gas/arc/sexw.s                |    17 -
 gas/testsuite/gas/arc/sleep.d               |    12 +-
 gas/testsuite/gas/arc/sleep.s               |     2 +-
 gas/testsuite/gas/arc/sshift.d              |    44 -
 gas/testsuite/gas/arc/sshift.s              |    52 -
 gas/testsuite/gas/arc/st.d                  |    66 +-
 gas/testsuite/gas/arc/st.s                  |     8 +-
 gas/testsuite/gas/arc/sub.d                 |   140 +-
 gas/testsuite/gas/arc/sub.s                 |    69 +-
 gas/testsuite/gas/arc/swi.d                 |    12 +-
 gas/testsuite/gas/arc/warn.exp              |     2 +-
 gas/testsuite/gas/arc/warn.s                |    10 +-
 gas/testsuite/gas/arc/xor.d                 |   140 +-
 gas/testsuite/gas/arc/xor.s                 |    69 +-
 gas/testsuite/gas/elf/elf.exp               |     3 +-
 include/ChangeLog                           |     4 +
 include/dis-asm.h                           |     2 +-
 include/elf/ChangeLog                       |     9 +
 include/elf/arc-reloc.def                   |   456 +
 include/elf/arc.h                           |    32 +-
 include/elf/common.h                        |     3 +-
 include/opcode/ChangeLog                    |     6 +
 include/opcode/arc-func.h                   |   236 +
 include/opcode/arc.h                        |   608 +-
 ld/ChangeLog                                |    22 +
 ld/Makefile.am                              |    25 +-
 ld/Makefile.in                              |    30 +-
 ld/NEWS                                     |     2 +
 ld/configure.tgt                            |     6 +-
 ld/emulparams/arcebelf.sh                   |    15 +
 ld/emulparams/arcebelf_prof.sh              |    21 +
 ld/emulparams/arceblinux.sh                 |    17 +
 ld/emulparams/arceblinux_prof.sh            |    23 +
 ld/emulparams/arcelf.sh                     |    21 +-
 ld/emulparams/arcelf_prof.sh                |    25 +
 ld/emulparams/arclinux.sh                   |    21 +
 ld/emulparams/arclinux_prof.sh              |    27 +
 ld/emulparams/arcv2elf.sh                   |    25 +
 ld/emulparams/arcv2elfx.sh                  |    22 +
 ld/emultempl/arclinux.em                    |    52 +
 ld/scripttempl/arclinux.sc                  |   439 +
 ld/scripttempl/elf32msp430.sc               |    11 +-
 ld/scripttempl/elf32msp430_3.sc             |    11 +-
 ld/scripttempl/elfarc.sc                    |   441 +
 ld/scripttempl/elfarcv2.sc                  |   314 +
 ld/testsuite/ChangeLog                      |     4 +
 ld/testsuite/ld-elf/linkonce1.d             |     2 +-
 opcodes/ChangeLog                           |    11 +
 opcodes/arc-dis.c                           |  1499 +--
 opcodes/arc-dis.h                           |    45 +-
 opcodes/arc-ext.c                           |   558 +-
 opcodes/arc-ext.h                           |    90 +-
 opcodes/arc-fxi.h                           |  1317 ++
 opcodes/arc-opc.c                           |  2661 ++--
 opcodes/arc-regs.h                          |   403 +
 opcodes/arc-tbl.h                           | 18198 ++++++++++++++++++++++++++
 140 files changed, 31685 insertions(+), 8148 deletions(-)

diff --git a/bfd/ChangeLog b/bfd/ChangeLog
index b2a8855..e84205f 100644
--- a/bfd/ChangeLog
+++ b/bfd/ChangeLog
@@ -1,3 +1,15 @@
+2015-10-07  Cupertino Miranda  <cmiranda@synopsys.com>
+
+	* archures.c: Remove support for older ARC. Added support for new
+	ARC cpus (ARC600, ARC601, ARC700, ARCV2).
+	* bfd-in2.h: Likewise.
+	* config.bfd: Likewise.
+	* cpu-arc.c: Likewise.
+	* elf32-arc.c: Totally changed file with a refactored
+	inplementation of the ARC port.
+	* libbfd.h: Added ARC specific relocation types.
+	* reloc.c: Likewise.
+
 2015-10-06  H.J. Lu  <hongjiu.lu@intel.com>
 
 	* bfd.c (bfd_update_compression_header): Clear the ch_reserved
diff --git a/bfd/archures.c b/bfd/archures.c
index 95433f8..51068b9 100644
--- a/bfd/archures.c
+++ b/bfd/archures.c
@@ -353,10 +353,12 @@ DESCRIPTION
 .#define bfd_mach_v850e2v3      0x45325633
 .#define bfd_mach_v850e3v5      0x45335635 {* ('E'|'3'|'V'|'5') *}
 .  bfd_arch_arc,       {* ARC Cores *}
-.#define bfd_mach_arc_5         5
-.#define bfd_mach_arc_6         6
-.#define bfd_mach_arc_7         7
-.#define bfd_mach_arc_8         8
+.#define bfd_mach_arc_a4        0
+.#define bfd_mach_arc_a5        1
+.#define bfd_mach_arc_arc600    2
+.#define bfd_mach_arc_arc601    4
+.#define bfd_mach_arc_arc700    3
+.#define bfd_mach_arc_arcv2     5
 . bfd_arch_m32c,     {* Renesas M16C/M32C.  *}
 .#define bfd_mach_m16c        0x75
 .#define bfd_mach_m32c        0x78
diff --git a/bfd/bfd-in2.h b/bfd/bfd-in2.h
index f4f98af..60d7e45 100644
--- a/bfd/bfd-in2.h
+++ b/bfd/bfd-in2.h
@@ -2148,10 +2148,12 @@ enum bfd_architecture
 #define bfd_mach_v850e2v3      0x45325633
 #define bfd_mach_v850e3v5      0x45335635 /* ('E'|'3'|'V'|'5') */
   bfd_arch_arc,       /* ARC Cores */
-#define bfd_mach_arc_5         5
-#define bfd_mach_arc_6         6
-#define bfd_mach_arc_7         7
-#define bfd_mach_arc_8         8
+#define bfd_mach_arc_a4        0
+#define bfd_mach_arc_a5        1
+#define bfd_mach_arc_arc600    2
+#define bfd_mach_arc_arc601    4
+#define bfd_mach_arc_arc700    3
+#define bfd_mach_arc_arcv2     5
  bfd_arch_m32c,     /* Renesas M16C/M32C.  */
 #define bfd_mach_m16c        0x75
 #define bfd_mach_m32c        0x78
@@ -3620,16 +3622,72 @@ pc-relative or some form of GOT-indirect relocation.  */
   BFD_RELOC_SH_GOTOFFFUNCDESC20,
   BFD_RELOC_SH_FUNCDESC,
 
-/* ARC Cores relocs.
-ARC 22 bit pc-relative branch.  The lowest two bits must be zero and are
-not stored in the instruction.  The high 20 bits are installed in bits 26
-through 7 of the instruction.  */
-  BFD_RELOC_ARC_B22_PCREL,
-
-/* ARC 26 bit absolute branch.  The lowest two bits must be zero and are not
-stored in the instruction.  The high 24 bits are installed in bits 23
-through 0.  */
-  BFD_RELOC_ARC_B26,
+/* ARC relocs.  */
+  BFD_RELOC_ARC_NONE,
+  BFD_RELOC_ARC_8,
+  BFD_RELOC_ARC_16,
+  BFD_RELOC_ARC_24,
+  BFD_RELOC_ARC_32,
+  BFD_RELOC_ARC_N8,
+  BFD_RELOC_ARC_N16,
+  BFD_RELOC_ARC_N24,
+  BFD_RELOC_ARC_N32,
+  BFD_RELOC_ARC_SDA,
+  BFD_RELOC_ARC_SECTOFF,
+  BFD_RELOC_ARC_S21H_PCREL,
+  BFD_RELOC_ARC_S21W_PCREL,
+  BFD_RELOC_ARC_S25H_PCREL,
+  BFD_RELOC_ARC_S25W_PCREL,
+  BFD_RELOC_ARC_SDA32,
+  BFD_RELOC_ARC_SDA_LDST,
+  BFD_RELOC_ARC_SDA_LDST1,
+  BFD_RELOC_ARC_SDA_LDST2,
+  BFD_RELOC_ARC_SDA16_LD,
+  BFD_RELOC_ARC_SDA16_LD1,
+  BFD_RELOC_ARC_SDA16_LD2,
+  BFD_RELOC_ARC_S13_PCREL,
+  BFD_RELOC_ARC_W,
+  BFD_RELOC_ARC_32_ME,
+  BFD_RELOC_ARC_32_ME_S,
+  BFD_RELOC_ARC_N32_ME,
+  BFD_RELOC_ARC_SECTOFF_ME,
+  BFD_RELOC_ARC_SDA32_ME,
+  BFD_RELOC_ARC_W_ME,
+  BFD_RELOC_AC_SECTOFF_U8,
+  BFD_RELOC_AC_SECTOFF_U8_1,
+  BFD_RELOC_AC_SECTOFF_U8_2,
+  BFD_RELOC_AC_SECTFOFF_S9,
+  BFD_RELOC_AC_SECTFOFF_S9_1,
+  BFD_RELOC_AC_SECTFOFF_S9_2,
+  BFD_RELOC_ARC_SECTOFF_ME_1,
+  BFD_RELOC_ARC_SECTOFF_ME_2,
+  BFD_RELOC_ARC_SECTOFF_1,
+  BFD_RELOC_ARC_SECTOFF_2,
+  BFD_RELOC_ARC_SDA16_ST2,
+  BFD_RELOC_ARC_PC32,
+  BFD_RELOC_ARC_GOT32,
+  BFD_RELOC_ARC_GOTPC32,
+  BFD_RELOC_ARC_PLT32,
+  BFD_RELOC_ARC_COPY,
+  BFD_RELOC_ARC_GLOB_DAT,
+  BFD_RELOC_ARC_JMP_SLOT,
+  BFD_RELOC_ARC_RELATIVE,
+  BFD_RELOC_ARC_GOTOFF,
+  BFD_RELOC_ARC_GOTPC,
+  BFD_RELOC_ARC_S21W_PCREL_PLT,
+  BFD_RELOC_ARC_S25H_PCREL_PLT,
+  BFD_RELOC_ARC_TLS_DTPMOD,
+  BFD_RELOC_ARC_TLS_TPOFF,
+  BFD_RELOC_ARC_TLS_GD_GOT,
+  BFD_RELOC_ARC_TLS_GD_LD,
+  BFD_RELOC_ARC_TLS_GD_CALL,
+  BFD_RELOC_ARC_TLS_IE_GOT,
+  BFD_RELOC_ARC_TLS_DTPOFF,
+  BFD_RELOC_ARC_TLS_DTPOFF_S9,
+  BFD_RELOC_ARC_TLS_LE_S9,
+  BFD_RELOC_ARC_TLS_LE_32,
+  BFD_RELOC_ARC_S25W_PCREL_PLT,
+  BFD_RELOC_ARC_S21H_PCREL_PLT,
 
 /* ADI Blackfin 16 bit immediate absolute reloc.  */
   BFD_RELOC_BFIN_16_IMM,
diff --git a/bfd/config.bfd b/bfd/config.bfd
index 30b45b5..fe43153 100644
--- a/bfd/config.bfd
+++ b/bfd/config.bfd
@@ -93,6 +93,7 @@ case "${targ_cpu}" in
 aarch64*)	 targ_archs="bfd_aarch64_arch bfd_arm_arch";;
 alpha*)		 targ_archs=bfd_alpha_arch ;;
 am34*|am33_2.0*) targ_archs=bfd_mn10300_arch ;;
+arc*)		 targ_archs=bfd_arc_arch ;;
 arm*)		 targ_archs=bfd_arm_arch ;;
 bfin*)		 targ_archs=bfd_bfin_arch ;;
 c30*)		 targ_archs=bfd_tic30_arch ;;
@@ -262,7 +263,7 @@ case "${targ}" in
     targ_defvec=am33_elf32_linux_vec
     ;;
 
-  arc-*-elf*)
+  arc*-*-elf* | arc*-*-linux-uclibc*)
     targ_defvec=arc_elf32_le_vec
     targ_selvecs=arc_elf32_be_vec
     ;;
diff --git a/bfd/cpu-arc.c b/bfd/cpu-arc.c
index a99e539..8bf4393 100644
--- a/bfd/cpu-arc.c
+++ b/bfd/cpu-arc.c
@@ -42,22 +42,24 @@
 
 static const bfd_arch_info_type arch_info_struct[] =
 {
-  ARC ( bfd_mach_arc_5, "arc5", FALSE, &arch_info_struct[1] ),
-  ARC ( bfd_mach_arc_5, "base", FALSE, &arch_info_struct[2] ),
-  ARC ( bfd_mach_arc_6, "arc6", FALSE, &arch_info_struct[3] ),
-  ARC ( bfd_mach_arc_7, "arc7", FALSE, &arch_info_struct[4] ),
-  ARC ( bfd_mach_arc_8, "arc8", FALSE, NULL ),
+  ARC (bfd_mach_arc_arc600, "ARC600", FALSE, &arch_info_struct[1]),
+  ARC (bfd_mach_arc_arc600, "A6"    , FALSE, &arch_info_struct[2]),
+  ARC (bfd_mach_arc_arc601, "ARC601", FALSE, &arch_info_struct[3]),
+  ARC (bfd_mach_arc_arc700, "ARC700", FALSE, &arch_info_struct[4]),
+  ARC (bfd_mach_arc_arc700, "A7",     FALSE, &arch_info_struct[5]),
+  ARC (bfd_mach_arc_arcv2,  "ARCv2",  FALSE, &arch_info_struct[6]),
+  ARC (bfd_mach_arc_arcv2,  "EM",     FALSE, &arch_info_struct[7]),
+  ARC (bfd_mach_arc_arcv2,  "HS",     FALSE, NULL),
 };
 
 const bfd_arch_info_type bfd_arc_arch =
-  ARC ( bfd_mach_arc_6, "arc", TRUE, &arch_info_struct[0] );
+  ARC (bfd_mach_arc_arcv2,  "HS", TRUE, &arch_info_struct[0]);
 
 /* Utility routines.  */
 
 /* Given cpu type NAME, return its bfd_mach_arc_xxx value.
    Returns -1 if not found.  */
-
-int arc_get_mach (char *);
+int arc_get_mach (char *name);
 
 int
 arc_get_mach (char *name)
diff --git a/bfd/elf32-arc.c b/bfd/elf32-arc.c
index 07af56b..68a47ca 100644
--- a/bfd/elf32-arc.c
+++ b/bfd/elf32-arc.c
@@ -1,6 +1,6 @@
 /* ARC-specific support for 32-bit ELF
    Copyright (C) 1994-2015 Free Software Foundation, Inc.
-   Contributed by Doug Evans (dje@cygnus.com).
+   Contributed by Cupertino Miranda (cmiranda@synopsys.com).
 
    This file is part of BFD, the Binary File Descriptor library.
 
@@ -25,189 +25,348 @@
 #include "elf-bfd.h"
 #include "elf/arc.h"
 #include "libiberty.h"
+#include "opcode/arc-func.h"
+
+#define ARC_DEBUG(...)
+#define DEBUG(...) printf (__ARGV__)
+#define DEBUG_ARC_RELOC(A)
+
+struct arc_local_data
+{
+  bfd_vma	  sdata_begin_symbol_vma;
+  asection *      sdata_output_section;
+  bfd_vma	  got_symbol_vma;
+};
+
+struct arc_local_data global_arc_data =
+{
+  .sdata_begin_symbol_vma = 0,
+  .sdata_output_section = NULL,
+  .got_symbol_vma = 0,
+};
+
+struct dynamic_sections
+{
+  bfd_boolean	  initialized;
+  asection *      sgot;
+  asection *      srelgot;
+  asection *      sgotplt;
+  asection *      sdyn;
+  asection *      splt;
+  asection *      srelplt;
+};
+
+static struct dynamic_sections
+arc_create_dynamic_sections (bfd * abfd, struct bfd_link_info *info);
+
+enum dyn_section_types
+{
+  got = 0,
+  relgot,
+  gotplt,
+  dyn,
+  plt,
+  relplt,
+  DYN_SECTION_TYPES_END
+};
+
+const char * dyn_section_names[DYN_SECTION_TYPES_END] =
+{
+  ".got",
+  ".rela.got",
+  ".got.plt",
+  ".dynamic",
+  ".plt",
+  ".rela.plt"
+};
+
+/* The default symbols representing the init and fini dyn values.
+   TODO: Check what is the relation of those strings with arclinux.em
+   and DT_INIT.  */
+#define INIT_SYM_STRING "_init"
+#define FINI_SYM_STRING "_fini"
+
+char * init_str = INIT_SYM_STRING;
+char * fini_str = FINI_SYM_STRING;
+
+
+#define ARC_RELOC_HOWTO(TYPE, VALUE, SIZE, BITSIZE, RELOC_FUNCTION, OVERFLOW, FORMULA) \
+      case VALUE: \
+	return #TYPE; \
+	break;
+
+static ATTRIBUTE_UNUSED const char *
+reloc_type_to_name (unsigned int type)
+{
+  switch (type)
+    {
+      #include "elf/arc-reloc.def"
+
+      default:
+	return "UNKNOWN";
+	break;
+    }
+}
+#undef ARC_RELOC_HOWTO
 
 /* Try to minimize the amount of space occupied by relocation tables
    on the ROM (not that the ROM won't be swamped by other ELF overhead).  */
 
-#define USE_REL	1
+#define USE_REL 1
+
+static ATTRIBUTE_UNUSED bfd_boolean
+is_reloc_PC_relative (reloc_howto_type *howto)
+{
+  return (strstr (howto->name, "PC") != NULL) ? TRUE : FALSE;
+}
+
+static bfd_boolean
+is_reloc_SDA_relative (reloc_howto_type *howto)
+{
+  return (strstr (howto->name, "SDA") != NULL) ? TRUE : FALSE;
+}
+
+static bfd_boolean
+is_reloc_for_GOT (reloc_howto_type * howto)
+{
+  return (strstr (howto->name, "GOT") != NULL) ? TRUE : FALSE;
+}
+
+static bfd_boolean
+is_reloc_for_PLT (reloc_howto_type * howto)
+{
+  return (strstr (howto->name, "PLT") != NULL) ? TRUE : FALSE;
+}
+
+#define arc_bfd_get_8(A,B,C) bfd_get_8(A,B)
+#define arc_bfd_get_16(A,B,C) bfd_get_16(A,B)
+#define arc_bfd_put_8(A,B,C,D) bfd_put_8(A,B,C)
+#define arc_bfd_put_16(A,B,C,D) bfd_put_16(A,B,C)
+
+static long
+arc_bfd_get_32 (bfd * abfd, void *loc, asection * input_section)
+{
+  long insn = bfd_get_32 (abfd, loc);
+
+  if (!bfd_big_endian (abfd)
+      && input_section
+      && (input_section->flags & SEC_CODE))
+    insn = ((0x0000fffff & insn) << 16) | ((0xffff0000 & insn) >> 16);
+
+  return insn;
+}
+
+static void
+arc_bfd_put_32 (bfd * abfd, long insn, void *loc, asection * input_section)
+{
+  if (!bfd_big_endian (abfd)
+      && input_section
+      && (input_section->flags & SEC_CODE))
+    insn = ((0x0000fffff & insn) << 16) | ((0xffff0000 & insn) >> 16);
+
+  bfd_put_32 (abfd, insn, loc);
+}
 
 static bfd_reloc_status_type
-arc_elf_b22_pcrel (bfd * abfd,
-		   arelent * reloc_entry,
-		   asymbol * symbol,
-		   void * data,
-		   asection * input_section,
-		   bfd * output_bfd,
-		   char ** error_message)
-{
-  /* If linking, back up the final symbol address by the address of the
-     reloc.  This cannot be accomplished by setting the pcrel_offset
-     field to TRUE, as bfd_install_relocation will detect this and refuse
-     to install the offset in the first place, but bfd_perform_relocation
-     will still insist on removing it.  */
-  if (output_bfd == NULL)
-    reloc_entry->addend -= reloc_entry->address;
-
-  /* Fall through to the default elf reloc handler.  */
-  return bfd_elf_generic_reloc (abfd, reloc_entry, symbol, data,
-				input_section, output_bfd, error_message);
+arc_elf_reloc (bfd *abfd ATTRIBUTE_UNUSED,
+	       arelent *reloc_entry,
+	       asymbol *symbol_in,
+	       void *data ATTRIBUTE_UNUSED,
+	       asection *input_section,
+	       bfd *output_bfd,
+	       char ** error_message ATTRIBUTE_UNUSED)
+{
+  if (output_bfd != NULL)
+    {
+      reloc_entry->address += input_section->output_offset;
+
+      /* In case of relocateable link and if the reloc is against a
+	 section symbol, the addend needs to be adjusted according to
+	 where the section symbol winds up in the output section.  */
+      if ((symbol_in->flags & BSF_SECTION_SYM) && symbol_in->section)
+	reloc_entry->addend += symbol_in->section->output_offset;
+
+      return bfd_reloc_ok;
+    }
+
+  return bfd_reloc_continue;
+}
+
+
+#define ARC_RELOC_HOWTO(TYPE, VALUE, SIZE, BITSIZE, RELOC_FUNCTION, OVERFLOW, FORMULA) \
+  TYPE = VALUE,
+enum howto_list
+{
+#include "elf/arc-reloc.def"
+  HOWTO_LIST_LAST
+};
+#undef ARC_RELOC_HOWTO
+
+#define ARC_RELOC_HOWTO(TYPE, VALUE, RSIZE, BITSIZE, RELOC_FUNCTION, OVERFLOW, FORMULA) \
+  [TYPE] = HOWTO (R_##TYPE, 0, RSIZE, BITSIZE, FALSE, 0, complain_overflow_##OVERFLOW, arc_elf_reloc, #TYPE, FALSE, 0, 0, FALSE),
+
+static struct reloc_howto_struct elf_arc_howto_table[] =
+{
+#include "elf/arc-reloc.def"
+/* Example of what is generated by the preprocessor.  Currently kept as an example.
+ HOWTO (R_ARC_NONE, // Type.
+    0, // Rightshift.
+    2, // Size (0 = byte, 1 = short, 2 = long).
+    32, // Bitsize.
+    FALSE, // PC_relative.
+    0, // Bitpos.
+    complain_overflow_bitfield, // Complain_on_overflow.
+    bfd_elf_generic_reloc, // Special_function.
+    "R_ARC_NONE", // Name.
+    TRUE, // Partial_inplace.
+    0, // Src_mask.
+    0, // Dst_mask.
+    FALSE), // PCrel_offset.
+*/
+};
+#undef ARC_RELOC_HOWTO
+
+static void arc_elf_howto_init (void)
+{
+#define ARC_RELOC_HOWTO(TYPE, VALUE, SIZE, BITSIZE, RELOC_FUNCTION, OVERFLOW, FORMULA) \
+  elf_arc_howto_table[TYPE].pc_relative = (strstr (#FORMULA, " P ") != NULL);
+
+  #include "elf/arc-reloc.def"
 }
+#undef ARC_RELOC_HOWTO
 
-static reloc_howto_type elf_arc_howto_table[] =
-{
-  /* This reloc does nothing.  */
-  HOWTO (R_ARC_NONE,		/* Type.  */
-	 0,			/* Rightshift.  */
-	 3,			/* Size (0 = byte, 1 = short, 2 = long).  */
-	 0,			/* Bitsize.  */
-	 FALSE,			/* PC_relative.  */
-	 0,			/* Bitpos.  */
-	 complain_overflow_bitfield, /* Complain_on_overflow.  */
-	 bfd_elf_generic_reloc,	/* Special_function.  */
-	 "R_ARC_NONE",		/* Name.  */
-	 TRUE,			/* Partial_inplace.  */
-	 0,			/* Src_mask.  */
-	 0,			/* Dst_mask.  */
-	 FALSE),		/* PCrel_offset.  */
-
-  /* A standard 32 bit relocation.  */
-  HOWTO (R_ARC_32,		/* Type.  */
-	 0,			/* Rightshift.  */
-	 2,			/* Size (0 = byte, 1 = short, 2 = long).  */
-	 32,			/* Bitsize.  */
-	 FALSE,			/* PC_relative.  */
-	 0,			/* Bitpos.  */
-	 complain_overflow_bitfield, /* Complain_on_overflow.  */
-	 bfd_elf_generic_reloc,	/* Special_function.  */
-	 "R_ARC_32",		/* Name.  */
-	 TRUE,			/* Partial_inplace.  */
-	 0xffffffff,		/* Src_mask.  */
-	 0xffffffff,		/* Dst_mask.  */
-	 FALSE),		/* PCrel_offset.  */
-
-  /* A 26 bit absolute branch, right shifted by 2.  */
-  HOWTO (R_ARC_B26,		/* Type.  */
-	 2,			/* Rightshift.  */
-	 2,			/* Size (0 = byte, 1 = short, 2 = long).  */
-	 26,			/* Bitsize.  */
-	 FALSE,			/* PC_relative.  */
-	 0,			/* Bitpos.  */
-	 complain_overflow_bitfield, /* Complain_on_overflow.  */
-	 bfd_elf_generic_reloc,	/* Special_function.  */
-	 "R_ARC_B26",		/* Name.  */
-	 TRUE,			/* Partial_inplace.  */
-	 0x00ffffff,		/* Src_mask.  */
-	 0x00ffffff,		/* Dst_mask.  */
-	 FALSE),		/* PCrel_offset.  */
-
-  /* A relative 22 bit branch; bits 21-2 are stored in bits 26-7.  */
-  HOWTO (R_ARC_B22_PCREL,	/* Type.  */
-	 2,			/* Rightshift.  */
-	 2,			/* Size (0 = byte, 1 = short, 2 = long).  */
-	 22,			/* Bitsize.  */
-	 TRUE,			/* PC_relative.  */
-	 7,			/* Bitpos.  */
-	 complain_overflow_signed, /* Complain_on_overflow.  */
-	 arc_elf_b22_pcrel,	/* Special_function.  */
-	 "R_ARC_B22_PCREL",	/* Name.  */
-	 TRUE,			/* Partial_inplace.  */
-	 0x07ffff80,		/* Src_mask.  */
-	 0x07ffff80,		/* Dst_mask.  */
-	 FALSE),		/* PCrel_offset.  */
+
+#define ARC_RELOC_HOWTO(TYPE, VALUE, SIZE, BITSIZE, RELOC_FUNCTION, OVERFLOW, FORMULA) \
+  [TYPE] = VALUE,
+const int howto_table_lookup[] =
+{
+  #include "elf/arc-reloc.def"
 };
+#undef ARC_RELOC_HOWTO
+
+#define ARC_ELF_HOWTO(r_type) \
+  (&elf_arc_howto_table[r_type])
 
 /* Map BFD reloc types to ARC ELF reloc types.  */
 
 struct arc_reloc_map
 {
   bfd_reloc_code_real_type bfd_reloc_val;
-  unsigned char elf_reloc_val;
+  unsigned char   elf_reloc_val;
 };
 
+#define ARC_RELOC_HOWTO(TYPE, VALUE, SIZE, BITSIZE, RELOC_FUNCTION, OVERFLOW, FORMULA) \
+  { BFD_RELOC_##TYPE, R_##TYPE },
 static const struct arc_reloc_map arc_reloc_map[] =
 {
-  { BFD_RELOC_NONE, R_ARC_NONE, },
-  { BFD_RELOC_32, R_ARC_32 },
-  { BFD_RELOC_CTOR, R_ARC_32 },
-  { BFD_RELOC_ARC_B26, R_ARC_B26 },
-  { BFD_RELOC_ARC_B22_PCREL, R_ARC_B22_PCREL },
+  #include "elf/arc-reloc.def"
+  {BFD_RELOC_NONE,  R_ARC_NONE},
+  {BFD_RELOC_8,  R_ARC_8},
+  {BFD_RELOC_16, R_ARC_16},
+  {BFD_RELOC_24, R_ARC_24},
+  {BFD_RELOC_32, R_ARC_32},
 };
+#undef ARC_RELOC_HOWTO
 
 static reloc_howto_type *
-bfd_elf32_bfd_reloc_type_lookup (bfd *abfd ATTRIBUTE_UNUSED,
+bfd_elf32_bfd_reloc_type_lookup (bfd * abfd ATTRIBUTE_UNUSED,
 				 bfd_reloc_code_real_type code)
 {
   unsigned int i;
+  static int fully_initialized = FALSE;
+
+  if (fully_initialized == FALSE)
+    {
+      arc_elf_howto_init ();
+      fully_initialized = TRUE; /* TODO: CHECK THIS IF IT STOPS WORKING.  */
+    }
 
   for (i = ARRAY_SIZE (arc_reloc_map); i--;)
-    if (arc_reloc_map[i].bfd_reloc_val == code)
-      return elf_arc_howto_table + arc_reloc_map[i].elf_reloc_val;
+    {
+      if (arc_reloc_map[i].bfd_reloc_val == code)
+	return elf_arc_howto_table + arc_reloc_map[i].elf_reloc_val;
+    }
 
   return NULL;
 }
 
 static reloc_howto_type *
-bfd_elf32_bfd_reloc_name_lookup (bfd *abfd ATTRIBUTE_UNUSED,
-				 const char *r_name)
+bfd_elf32_bfd_reloc_name_lookup (bfd * abfd ATTRIBUTE_UNUSED, const char *r_name)
 {
   unsigned int i;
 
-  for (i = 0;
-       i < sizeof (elf_arc_howto_table) / sizeof (elf_arc_howto_table[0]);
-       i++)
+  for (i = 0; i < ARRAY_SIZE (elf_arc_howto_table); i++)
     if (elf_arc_howto_table[i].name != NULL
 	&& strcasecmp (elf_arc_howto_table[i].name, r_name) == 0)
-      return &elf_arc_howto_table[i];
+      return elf_arc_howto_table + i;
 
   return NULL;
 }
 
-/* Set the howto pointer for an ARC ELF reloc.  */
 
+/* Set the howto pointer for an ARC ELF reloc.  */
 static void
-arc_info_to_howto_rel (bfd *abfd ATTRIBUTE_UNUSED,
-		       arelent *cache_ptr,
-		       Elf_Internal_Rela *dst)
+arc_info_to_howto_rel (bfd * abfd ATTRIBUTE_UNUSED,
+		       arelent * cache_ptr,
+		       Elf_Internal_Rela * dst)
 {
   unsigned int r_type;
 
   r_type = ELF32_R_TYPE (dst->r_info);
-  if (r_type >= (unsigned int) R_ARC_max)
-    {
-      _bfd_error_handler (_("%B: invalid ARC reloc number: %d"), abfd, r_type);
-      r_type = 0;
-    }
+  BFD_ASSERT (r_type < (unsigned int) R_ARC_max);
   cache_ptr->howto = &elf_arc_howto_table[r_type];
 }
 
 /* Set the right machine number for an ARC ELF file.  */
-
 static bfd_boolean
-arc_elf_object_p (bfd *abfd)
+arc_elf_object_p (bfd * abfd)
 {
-  unsigned int mach = bfd_mach_arc_6;
+  /* Make sure this is initialised, or you'll have the potential of passing
+     garbage---or misleading values---into the call to
+     bfd_default_set_arch_mach ().  */
+  int		  mach = bfd_mach_arc_arc700;
+  unsigned long   arch = elf_elfheader (abfd)->e_flags & EF_ARC_MACH_MSK;
+  unsigned	  e_machine = elf_elfheader (abfd)->e_machine;
 
-  if (elf_elfheader(abfd)->e_machine == EM_ARC)
+  if (e_machine == EM_ARC_COMPACT || e_machine == EM_ARC_COMPACT2)
     {
-      unsigned long arch = elf_elfheader (abfd)->e_flags & EF_ARC_MACH;
-
       switch (arch)
 	{
-	case E_ARC_MACH_ARC5:
-	  mach = bfd_mach_arc_5;
-	  break;
-	default:
-	case E_ARC_MACH_ARC6:
-	  mach = bfd_mach_arc_6;
-	  break;
-	case E_ARC_MACH_ARC7:
-	  mach = bfd_mach_arc_7;
-	  break;
-	case E_ARC_MACH_ARC8:
-	  mach = bfd_mach_arc_8;
-	  break;
+	  case E_ARC_MACH_ARC600:
+	    mach = bfd_mach_arc_arc600;
+	    break;
+	  case E_ARC_MACH_ARC601:
+	    mach = bfd_mach_arc_arc601;
+	    break;
+	  case E_ARC_MACH_ARC700:
+	    mach = bfd_mach_arc_arc700;
+	    break;
+	  case EF_ARC_CPU_ARCV2HS:
+	  case EF_ARC_CPU_ARCV2EM:
+	    mach = bfd_mach_arc_arcv2;
+	    break;
+	  default:
+	    mach = (e_machine == EM_ARC_COMPACT) ?
+	      bfd_mach_arc_arc700 : bfd_mach_arc_arcv2;
+	    break;
+	}
+    }
+  else
+    {
+      if (e_machine == EM_ARC)
+	{
+	  (*_bfd_error_handler)
+	    (_("Error: The ARC4 architecture is no longer supported.\n"));
+	  return FALSE;
+	}
+      else
+	{
+	  (*_bfd_error_handler)
+	    (_("Warning: unset or old architecture flags. \n"
+	       "	       Use default machine.\n"));
 	}
     }
+
   return bfd_default_set_arch_mach (abfd, bfd_arch_arc, mach);
 }
 
@@ -215,42 +374,1323 @@ arc_elf_object_p (bfd *abfd)
    This gets the ARC architecture right based on the machine number.  */
 
 static void
-arc_elf_final_write_processing (bfd *abfd,
-				bfd_boolean linker ATTRIBUTE_UNUSED)
+arc_elf_final_write_processing (bfd * abfd, bfd_boolean linker ATTRIBUTE_UNUSED)
 {
   unsigned long val;
+  unsigned long emf;
 
   switch (bfd_get_mach (abfd))
     {
-    case bfd_mach_arc_5:
-      val = E_ARC_MACH_ARC5;
+    case bfd_mach_arc_arc600:
+      val = E_ARC_MACH_ARC600;
+      emf = EM_ARC_COMPACT;
       break;
-    default:
-    case bfd_mach_arc_6:
-      val = E_ARC_MACH_ARC6;
+    case bfd_mach_arc_arc601:
+      val = E_ARC_MACH_ARC601;
+      emf = EM_ARC_COMPACT;
       break;
-    case bfd_mach_arc_7:
-      val = E_ARC_MACH_ARC7;
+    case bfd_mach_arc_arc700:
+      val = E_ARC_MACH_ARC700;
+      emf = EM_ARC_COMPACT;
       break;
-    case bfd_mach_arc_8:
-      val = E_ARC_MACH_ARC8;
+    case bfd_mach_arc_arcv2:
+      val = EF_ARC_CPU_GENERIC;
+      emf = EM_ARC_COMPACT2;
+      /* TODO: Check validity of this.  It can also be ARCV2EM here.
+	 Previous version sets the e_machine here.  */
       break;
+    default:
+      abort ();
     }
-  elf_elfheader (abfd)->e_flags &=~ EF_ARC_MACH;
+  elf_elfheader (abfd)->e_flags &= ~EF_ARC_MACH;
   elf_elfheader (abfd)->e_flags |= val;
+  elf_elfheader (abfd)->e_machine = emf;
+
+  /* Record whatever is the current syscall ABI version.  */
+  elf_elfheader (abfd)->e_flags |= E_ARC_OSABI_CURRENT;
 }
 
+#define BFD_DEBUG_PIC(...)
+
+struct arc_relocation_data
+{
+  bfd_vma	  reloc_offset;
+  bfd_vma	  reloc_addend;
+  bfd_vma	  got_offset_value;
+
+  bfd_vma	  sym_value;
+  asection *	  sym_section;
+
+  reloc_howto_type *howto;
+
+  asection *	  input_section;
+
+  bfd_vma	  sdata_begin_symbol_vma;
+  bfd_boolean	  sdata_begin_symbol_vma_set;
+  bfd_vma	  got_symbol_vma;
+
+  bfd_boolean	  should_relocate;
+};
+
+static void
+debug_arc_reloc (struct arc_relocation_data reloc_data)
+{
+  fprintf (stderr, "Reloc type=%s, should_relocate = %s\n",
+	   reloc_data.howto->name,
+	   reloc_data.should_relocate ? "true" : "false");
+  fprintf (stderr, "  offset = 0x%x, addend = 0x%x\n",
+	   (unsigned int) reloc_data.reloc_offset,
+	   (unsigned int) reloc_data.reloc_addend);
+  fprintf (stderr, " Symbol:\n");
+  fprintf (stderr, "  value = 0x%08x\n",
+	   (unsigned int) reloc_data.sym_value);
+  if (reloc_data.sym_section != NULL)
+    {
+      fprintf (stderr, "IN IF\n");
+      fprintf (stderr,
+	       "  section name = %s, output_offset 0x%08x, output_section->vma = 0x%08x\n",
+	       reloc_data.sym_section->name,
+	       (unsigned int) reloc_data.sym_section->output_offset,
+	       (unsigned int) reloc_data.sym_section->output_section->vma);
+    }
+  else
+    fprintf (stderr, "	symbol section is NULL\n");
+
+  fprintf (stderr, " Input_section:\n");
+  if (reloc_data.input_section != NULL)
+    {
+      fprintf (stderr,
+	       "  section name = %s, output_offset 0x%08x, output_section->vma = 0x%08x\n",
+	       reloc_data.input_section->name,
+	       (unsigned int) reloc_data.input_section->output_offset,
+	       (unsigned int) reloc_data.input_section->output_section->vma);
+      fprintf (stderr, "  changed_address = 0x%08x\n",
+	       (unsigned int) (reloc_data.input_section->output_section->vma +
+	       reloc_data.input_section->output_offset +
+	       reloc_data.reloc_offset));
+    }
+  else
+    fprintf (stderr, "	input section is NULL\n");
+}
+
+#define S (reloc_data.sym_value \
+	   + reloc_data.sym_section->output_offset \
+	   + reloc_data.sym_section->output_section->vma)
+#define A (reloc_data.reloc_addend)
+#define B (0)
+#define G (reloc_data.got_offset_value)
+#define GOT (reloc_data.got_symbol_vma + 12)
+#define L (reloc_data.sym_value \
+	   + reloc_data.sym_section->output_section->vma \
+	   + reloc_data.sym_section->output_offset)
+#define MES (0)
+	/* P: relative offset to PCL The offset should be to the current location
+	   aligned to 32 bits.  */
+#define P ( \
+	    (reloc_data.input_section->output_section->vma \
+	     + reloc_data.input_section->output_offset \
+	     + (reloc_data.reloc_offset - (bitsize >= 32 ? 4 : 0)) \
+	    ) & ~0x3)
+#define SECTSTAR (reloc_data.input_section->output_offset)
+#define SECTSTART (reloc_data.input_section->output_offset)
+#define _SDA_BASE_ (reloc_data.sdata_begin_symbol_vma)
+
+#define none (0)
+
+#define ARC_RELOC_HOWTO(TYPE, VALUE, SIZE, BITSIZE, RELOC_FUNCTION, OVERFLOW, FORMULA) \
+  case R_##TYPE: \
+    { \
+      bfd_vma bitsize ATTRIBUTE_UNUSED = BITSIZE; \
+      relocation = FORMULA  ; \
+      insn = RELOC_FUNCTION (insn, relocation); \
+    } \
+    break;
+
+static bfd_reloc_status_type
+arc_do_relocation (bfd_byte * contents, struct arc_relocation_data reloc_data)
+{
+  bfd_vma relocation = 0;
+  bfd_vma insn;
+  bfd_vma orig_insn ATTRIBUTE_UNUSED;
+
+  if (reloc_data.should_relocate == FALSE)
+    return bfd_reloc_notsupported;
+
+  switch (reloc_data.howto->size)
+    {
+      case 2:
+	insn = arc_bfd_get_32 (reloc_data.input_section->owner,
+			       contents + reloc_data.reloc_offset,
+			       reloc_data.input_section);
+	break;
+      case 1:
+      case 0:
+	insn = arc_bfd_get_16 (reloc_data.input_section->owner,
+			       contents + reloc_data.reloc_offset,
+			       reloc_data.input_section);
+	break;
+      default:
+	insn = 0;
+	BFD_ASSERT (0);
+	break;
+    }
+
+  orig_insn = insn;
+
+  switch (reloc_data.howto->type)
+    {
+      #include "elf/arc-reloc.def"
+
+      default:
+	BFD_ASSERT (0);
+	break;
+    }
+
+  /* Check for relocation overflow.  */
+  if (reloc_data.howto->complain_on_overflow != complain_overflow_dont)
+    {
+      bfd_reloc_status_type flag;
+      flag = bfd_check_overflow (reloc_data.howto->complain_on_overflow,
+				 reloc_data.howto->bitsize,
+				 reloc_data.howto->rightshift,
+				 bfd_arch_bits_per_address (reloc_data.input_section->owner),
+				 relocation);
+
+#undef DEBUG_ARC_RELOC
+#define DEBUG_ARC_RELOC(A) debug_arc_reloc (A)
+      if (flag != bfd_reloc_ok)
+	{
+	  fprintf (stderr, "Relocation overflows !!!!\n");
+
+	  DEBUG_ARC_RELOC (reloc_data);
+
+	  fprintf (stderr,
+		  "Relocation value = signed -> %d, unsigned -> %u, hex -> (0x%08x)\n",
+		  (int) relocation,
+		  (unsigned int) relocation,
+		  (unsigned int) relocation);
+	  return flag;
+	}
+    }
+#undef DEBUG_ARC_RELOC
+#define DEBUG_ARC_RELOC(A)
+
+  switch (reloc_data.howto->size)
+    {
+      case 2:
+	arc_bfd_put_32 (reloc_data.input_section->owner, insn,
+		       contents + reloc_data.reloc_offset,
+		       reloc_data.input_section);
+	break;
+      case 1:
+      case 0:
+	arc_bfd_put_16 (reloc_data.input_section->owner, insn,
+		       contents + reloc_data.reloc_offset,
+		       reloc_data.input_section);
+	break;
+      default:
+	ARC_DEBUG ("size = %d\n", reloc_data.howto->size);
+	BFD_ASSERT (0);
+	break;
+    }
+
+  return bfd_reloc_ok;
+}
+#undef S
+#undef A
+#undef B
+#undef G
+#undef GOT
+#undef L
+#undef MES
+#undef P
+#undef SECTSTAR
+#undef SECTSTART
+#undef _SDA_BASE_
+#undef none
+
+#undef ARC_RELOC_HOWTO
+
+static bfd_vma *
+arc_get_local_got_offsets (bfd * abfd)
+{
+  static bfd_vma *local_got_offsets = NULL;
+
+  if (local_got_offsets == NULL)
+    {
+      size_t	   size;
+      unsigned int i;
+      Elf_Internal_Shdr *symtab_hdr = &((elf_tdata (abfd))->symtab_hdr);
+
+      size = symtab_hdr->sh_info * sizeof (bfd_vma);
+      local_got_offsets = (bfd_vma *) bfd_alloc (abfd, size);
+      if (local_got_offsets == NULL)
+	return FALSE;
+      elf_local_got_offsets (abfd) = local_got_offsets;
+      for (i = 0; i < symtab_hdr->sh_info; i++)
+	local_got_offsets[i] = (bfd_vma) - 1;
+    }
+
+  return local_got_offsets;
+}
+
+
+/* Relocate an arc ELF section.
+   Function : elf_arc_relocate_section
+   Brief    : Relocate an arc section, by handling all the relocations
+  	     appearing in that section.
+   Args     : output_bfd    : The bfd being written to.
+  	      info	    : Link information.
+  	      input_bfd     : The input bfd.
+  	      input_section : The section being relocated.
+  	      contents	    : contents of the section being relocated.
+  	      relocs	    : List of relocations in the section.
+  	      local_syms    : is a pointer to the swapped in local symbols.
+  	      local_section : is an array giving the section in the input file
+  			      corresponding to the st_shndx field of each
+  			      local symbol.  */
+static bfd_boolean
+elf_arc_relocate_section (bfd *                   output_bfd,
+			  struct bfd_link_info *  info,
+			  bfd *                   input_bfd,
+			  asection *              input_section,
+			  bfd_byte *              contents,
+			  Elf_Internal_Rela *     relocs,
+			  Elf_Internal_Sym *      local_syms,
+			  asection **             local_sections)
+{
+  Elf_Internal_Shdr *           symtab_hdr;
+  struct elf_link_hash_entry ** sym_hashes;
+  bfd_vma *                     local_got_offsets;
+  Elf_Internal_Rela *           rel;
+  Elf_Internal_Rela *           relend;
+
+  symtab_hdr = &((elf_tdata (input_bfd))->symtab_hdr);
+  sym_hashes = elf_sym_hashes (input_bfd);
+
+  rel = relocs;
+  relend = relocs + input_section->reloc_count;
+  for (; rel < relend; rel++)
+    {
+      enum elf_arc_reloc_type       r_type;
+      reloc_howto_type *            howto;
+      unsigned long                 r_symndx;
+      struct elf_link_hash_entry *  h;
+      Elf_Internal_Sym *            sym;
+      asection *                    sec;
+
+      struct arc_relocation_data reloc_data =
+      {
+	.reloc_offset = 0,	/* bfd_vma reloc_offset; */
+	.reloc_addend = 0,	/* bfd_vma reloc_addend; */
+	.got_offset_value = 0,	/* bfd_vma got_offset_value; */
+	.sym_value = 0,		/* bfd_vma sym_value; */
+	.sym_section = NULL,	/* asection *sym_section; */
+	.howto = NULL,		/* reloc_howto_type *howto; */
+	.input_section = NULL,	/* asection *input_section; */
+	.sdata_begin_symbol_vma = 0,	/* bfd_vma sdata_begin_symbol_vma; */
+	.sdata_begin_symbol_vma_set = FALSE,	/* bfd_vma sdata_begin_symbol_vma_set; */
+	.got_symbol_vma = 0,	/* bfd_vma got_symbol_vma; */
+	.should_relocate = FALSE	/* bfd_boolean should_relocate; */
+      };
+
+      struct elf_link_hash_entry *h2;
+
+      h2 = elf_link_hash_lookup (elf_hash_table (info), "__SDATA_BEGIN__",
+				 FALSE, FALSE, TRUE);
+
+      if (reloc_data.sdata_begin_symbol_vma_set == FALSE
+	    && h2 != NULL && h2->root.type != bfd_link_hash_undefined)
+	{
+	  reloc_data.sdata_begin_symbol_vma =
+	    (h2->root.u.def.value +
+	     h2->root.u.def.section->output_section->vma);
+	  reloc_data.sdata_begin_symbol_vma_set = TRUE;
+	}
+
+      h2 = elf_link_hash_lookup (elf_hash_table (info),
+				 "_GLOBAL_OFFSET_TABLE_", FALSE, FALSE,
+				 TRUE);
+      if (h2 != NULL && h2->root.type != bfd_link_hash_undefined)
+	{
+	  reloc_data.got_symbol_vma =
+	      (h2->root.u.def.value +
+	       h2->root.u.def.section->output_section->vma);
+	}
+
+      r_type = ELF32_R_TYPE (rel->r_info);
+
+      if (r_type >= (int) R_ARC_max)
+	{
+	  bfd_set_error (bfd_error_bad_value);
+	  return FALSE;
+	}
+      howto = &elf_arc_howto_table[r_type];
+
+      reloc_data.input_section = input_section;
+      reloc_data.howto = howto;
+      reloc_data.reloc_offset = rel->r_offset;
+      reloc_data.reloc_addend = rel->r_addend;
+
+      r_symndx = ELF32_R_SYM (rel->r_info);
+
+      /* This is a final link.  */
+      h = NULL;
+      sym = NULL;
+      sec = NULL;
+
+      if (r_symndx < symtab_hdr->sh_info) /* A local symbol.  */
+	{
+	  sym = local_syms + r_symndx;
+	  sec = local_sections[r_symndx];
+
+	  reloc_data.sym_value = sym->st_value;
+	  reloc_data.sym_section = sec;
+
+	    if (is_reloc_for_GOT (reloc_data.howto))
+	      {
+		local_got_offsets = arc_get_local_got_offsets (output_bfd);
+		reloc_data.got_offset_value = local_got_offsets[r_symndx];
+	      }
+
+	  reloc_data.should_relocate = TRUE;
+	}
+      else /* Global symbol.  */
+	{
+	  /* Get the symbol's entry in the symtab.  */
+	  h = sym_hashes[r_symndx - symtab_hdr->sh_info];
+
+	  while (h->root.type == bfd_link_hash_indirect
+		 || h->root.type == bfd_link_hash_warning)
+	    h = (struct elf_link_hash_entry *) h->root.u.i.link;
+
+	  BFD_ASSERT ((h->dynindx == -1) >= (h->forced_local != 0));
+	  /* If we have encountered a definition for this symbol.  */
+	  if (h->root.type == bfd_link_hash_defined
+	      || h->root.type == bfd_link_hash_defweak)
+	    {
+	      reloc_data.sym_value = h->root.u.def.value;
+	      reloc_data.sym_section = h->root.u.def.section;
+
+	      reloc_data.should_relocate = TRUE;
+
+	      if (is_reloc_for_GOT (howto))
+		{
+		  struct dynamic_sections ds =
+		  arc_create_dynamic_sections (output_bfd, info);
+
+		  /* TODO: Change it to use arc_do_relocation with ARC_32
+		     reloc.  */
+		  bfd_vma relocation =
+		    reloc_data.sym_value + reloc_data.reloc_addend
+		    + reloc_data.sym_section->output_offset
+		    + reloc_data.sym_section->output_section->vma;
+
+		  bfd_put_32 (output_bfd, relocation, ds.sgot->contents + h->got.offset);
+
+		}
+	    }
+	  else if (h->root.type == bfd_link_hash_undefweak)
+	    {
+	      /* Is weak symbol and has no definition.  */
+	      continue;
+	    }
+	  else
+	    {
+	      if (is_reloc_for_GOT (howto))
+		{
+		  struct dynamic_sections ds =
+		      arc_create_dynamic_sections (output_bfd, info);
+
+		  reloc_data.sym_value = h->root.u.def.value;
+		  reloc_data.sym_section = ds.sgot;
+
+		  reloc_data.should_relocate = TRUE;
+		}
+	      else if (is_reloc_for_PLT (howto))
+		{
+		  struct dynamic_sections ds =
+		    arc_create_dynamic_sections (output_bfd, info);
+
+		  reloc_data.sym_value = h->plt.offset;
+		  reloc_data.sym_section = ds.splt;
+
+		  reloc_data.should_relocate = TRUE;
+		}
+	      else if (!(*info->callbacks->undefined_symbol)
+		       (info, h->root.root.string, input_bfd, input_section,
+			rel->r_offset,!bfd_link_pic (info)))
+		{
+		  return FALSE;
+		}
+	    }
+
+	  reloc_data.got_offset_value = h->got.offset;
+	}
+
+      if (is_reloc_SDA_relative (howto) && reloc_data.sdata_begin_symbol_vma_set == FALSE)
+	{
+	  (*_bfd_error_handler)
+	      ("Error: Linker symbol __SDATA_BEGIN__ not found");
+	  bfd_set_error (bfd_error_bad_value);
+	  return FALSE;
+	}
+
+      DEBUG_ARC_RELOC (reloc_data);
+      if (arc_do_relocation (contents, reloc_data) != bfd_reloc_ok)
+	return FALSE;
+    }
+
+  return TRUE;
+}
+
+static struct dynamic_sections
+arc_create_dynamic_sections (bfd * abfd, struct bfd_link_info *info)
+{
+  static bfd * dynobj = NULL;
+  struct dynamic_sections ds =
+  {
+	.initialized = FALSE,
+	.sgot = NULL,
+	.srelgot = NULL,
+	.sgotplt = NULL,
+	.sdyn = NULL,
+	.splt = NULL,
+	.srelplt = NULL
+  };
+
+  if (dynobj == NULL)
+    {
+      elf_hash_table (info)->dynobj = dynobj = abfd;
+      if (!_bfd_elf_create_got_section (dynobj, info))
+	return ds;
+    }
+  else
+    dynobj = (elf_hash_table (info))->dynobj;
+
+  ds.sgot = bfd_get_section_by_name (dynobj, ".got");
+
+  ds.srelgot = bfd_get_section_by_name (dynobj, ".rela.got");
+  if (ds.srelgot == NULL)
+    {
+      ds.srelgot = bfd_make_section_with_flags (dynobj, ".rela.got",
+					 SEC_ALLOC
+					 | SEC_LOAD
+					 | SEC_HAS_CONTENTS
+					 | SEC_IN_MEMORY
+					 | SEC_LINKER_CREATED
+					 | SEC_READONLY);
+      if (ds.srelgot == NULL
+	  || !bfd_set_section_alignment (dynobj, ds.srelgot, 2))
+	return ds;
+    }
+
+  ds.sgotplt = bfd_get_section_by_name (dynobj, ".got.plt");
+
+  ds.sdyn = bfd_get_section_by_name (dynobj, ".dynamic");
+  ds.splt = bfd_get_section_by_name (dynobj, ".plt");
+  ds.srelplt = bfd_get_section_by_name (dynobj, ".rela.plt");
+
+  ds.initialized = TRUE;
+
+  return ds;
+}
+
+#define ADD_SYMBOL_REF_SEC_AND_RELOC(SECNAME, COND_FOR_RELOC, H) \
+  ds.s##SECNAME->size; \
+  { \
+    if (COND_FOR_RELOC) ds.srel##SECNAME->size += sizeof (Elf32_External_Rela); \
+    if (H)  \
+      if (h->dynindx == -1 && !h->forced_local) \
+	if (! bfd_elf_link_record_dynamic_symbol (info, H)) \
+	  return FALSE; \
+    ds.s##SECNAME->size += 4; \
+  }
+
+static bfd_boolean
+elf_arc_check_relocs (bfd *                      abfd,
+		      struct bfd_link_info *     info,
+		      asection *                 sec,
+		      const Elf_Internal_Rela *  relocs)
+{
+  Elf_Internal_Shdr *            symtab_hdr;
+  struct elf_link_hash_entry **  sym_hashes;
+  bfd_vma *                      local_got_offsets;
+  const Elf_Internal_Rela *      rel;
+  const Elf_Internal_Rela *      rel_end;
+  bfd *                          dynobj ATTRIBUTE_UNUSED;
+
+  dynobj = (elf_hash_table (info))->dynobj;
+  symtab_hdr = &((elf_tdata (abfd))->symtab_hdr);
+  sym_hashes = elf_sym_hashes (abfd);
+  local_got_offsets = arc_get_local_got_offsets (abfd);
+
+  struct dynamic_sections ds = arc_create_dynamic_sections (abfd, info);
+
+  rel_end = relocs + sec->reloc_count;
+  for (rel = relocs; rel < rel_end; rel++)
+    {
+      enum elf_arc_reloc_type r_type;
+      reloc_howto_type *howto;
+      unsigned long   r_symndx;
+      struct elf_link_hash_entry *h;
+
+      r_type = ELF32_R_TYPE (rel->r_info);
+
+      if (r_type >= (int) R_ARC_max)
+	{
+	  bfd_set_error (bfd_error_bad_value);
+	  return FALSE;
+	}
+      howto = &elf_arc_howto_table[r_type];
+
+      /* Load symbol information.  */
+      r_symndx = ELF32_R_SYM (rel->r_info);
+      if (r_symndx < symtab_hdr->sh_info) /* Is a local symbol.  */
+	h = NULL;
+      else /* Global one.  */
+	h = sym_hashes[r_symndx - symtab_hdr->sh_info];
+
+      if (is_reloc_for_PLT (howto) == TRUE)
+	{
+	  if (h == NULL)
+	    continue;
+	  else
+	    h->needs_plt = 1;
+	}
+
+      if (is_reloc_for_GOT (howto) == TRUE)
+	{
+	  if (h == NULL)
+	    {
+	      /* Local symbol.  */
+	      local_got_offsets[r_symndx] =
+		ADD_SYMBOL_REF_SEC_AND_RELOC (got, bfd_link_pic (info), NULL);
+	    }
+	  else
+	    {
+	      /* Global symbol.  */
+	      h = sym_hashes[r_symndx - symtab_hdr->sh_info];
+	      h->got.offset =
+		ADD_SYMBOL_REF_SEC_AND_RELOC (got, TRUE, h);
+	    }
+	}
+    }
+
+  return TRUE;
+}
+
+#define ELF_DYNAMIC_INTERPRETER  "/sbin/ld-uClibc.so"
+
+/* Size of one plt entry in bytes.  */
+#define PLT_ENTRY_SIZE	12
+#define PLT_ENTRY_SIZE_V2 16
+
+/* Instructions appear in memory as a sequence of half-words (16 bit);
+   individual half-words are represented on the target in target byte order.
+   We use 'unsigned short' on the host to represent the PLT templates,
+   and translate to target byte order as we copy to the target.  */
+typedef unsigned short insn_hword;
+
+
+/* TODO: Make this PLT entry code be in a separate object file.  */
+/* TODO: This is a linker BTW, we should be able to link. :)  */
+
+/* The zeroth entry in the absolute plt entry.  */
+static const insn_hword elf_arc_abs_plt0_entry[2 * PLT_ENTRY_SIZE / 2] =
+{
+  0x1600,	/* ld %r11, [0] */
+  0x700b,
+  0x0000,
+  0x0000,
+  0x1600,	/* ld %r10, [0] */
+  0x700a,	/* */
+  0,
+  0,
+  0x2020,	/* j [%r10] */
+  0x0280,	/* ---"---- */
+  0x0000,	/* pad */
+  0x0000	/* pad */
+};
+
+/* Contents of the subsequent entries in the absolute plt.  */
+static const insn_hword elf_arc_abs_pltn_entry[PLT_ENTRY_SIZE / 2] =
+{
+  0x2730,	/* ld %r12, [%pc,func@gotpc] */
+  0x7f8c,	/* ------ " " -------------- */
+  0x0000,	/* ------ " " -------------- */
+  0x0000,	/* ------ " " -------------- */
+  0x7c20,	/* j_s.d [%r12] */
+  0x74ef	/* mov_s %r12, %pcl */
+};
+
+/* The zeroth entry in the absolute plt entry for ARCv2.  */
+static const insn_hword elf_arcV2_abs_plt0_entry[2 * PLT_ENTRY_SIZE_V2 / 2] =
+{
+  0x1600, 0x700b, 0, 0,   /* ld %r11, [0] */
+  0x1600, 0x700a, 0, 0,   /* ld %r10, [0] */
+  0x2020, 0x0280,	  /* j [%r10] */
+  0x0000, 0x0000,	  /* -> RELOCATED TO ABS ADDRESS OF GOT <- */
+  0x0000,		  /* pad */
+  0x0000,		  /* pad */
+  0x0000,		  /* pad */
+  0x0000		  /* pad */
+};
+
+/* Contents of the subsequent entries in the absolute plt for ARCv2.  */
+static const insn_hword elf_arcV2_abs_pltn_entry[PLT_ENTRY_SIZE_V2 / 2] =
+{
+  0x2730,	/* ld %r12, [%pcl,func@gotpc] */
+  0x7f8c,	/* ------ " " -------------- */
+  0x0000,	/* ------ " " -------------- */
+  0x0000,	/* ------ " " -------------- */
+  0x2021,	/* j.d [%r12] */
+  0x0300,	/* ------ " " -------------- */
+  0x240a,	/* mov %r12, %pcl */
+  0x1fc0	/* ------ " " -------------- */
+};
+
+/* The zeroth entry in the pic plt entry.  */
+static const insn_hword elf_arc_pic_plt0_entry[2 * PLT_ENTRY_SIZE / 2] =
+{
+  0x2730,	/* ld %r11, [pcl,0] : 0 to be replaced by
+		   _DYNAMIC@GOTPC+4 */
+  0x7f8b,
+  0x0000,
+  0x0000,
+  0x2730,	/* ld %r10, [pcl,0] : 0 to be replaced by
+		   -DYNAMIC@GOTPC+8 */
+  0x7f8a,	/* */
+  0,
+  0,
+  0x2020,	/* j [%r10] */
+  0x0280,	/* ---"---- */
+  0x0000,	/* pad */
+  0x0000	/* pad */
+};
+
+/* Contents of the subsequent entries in the pic plt.  */
+static const insn_hword elf_arc_pic_pltn_entry[PLT_ENTRY_SIZE / 2] =
+{
+  0x2730,	/* ld %r12, [%pc,func@got] */
+  0x7f8c,	/* ------ " " -------------- */
+  0x0000,	/* ------ " " -------------- */
+  0x0000,	/* ------ " " -------------- */
+  0x7c20,	/* j_s.d [%r12] */
+  0x74ef,	/* mov_s %r12, %pcl */
+};
+
+/* The zeroth entry in the pic plt entry for ARCv2.  */
+static const insn_hword elf_arcV2_pic_plt0_entry[2 * PLT_ENTRY_SIZE_V2 / 2] =
+{
+  0x2730,	/* ld %r11, [pcl,0] : 0 to be replaced by
+		   _DYNAMIC@GOTPC+4 */
+  0x7f8b,
+  0x0000,
+  0x0000,
+  0x2730,	/* ld %r10, [pcl,0] : 0 to be replaced by
+		   -DYNAMIC@GOTPC+8 */
+  0x7f8a,	/* */
+  0,
+  0,
+  0x2020,	/* j [%r10] */
+  0x0280,	/* ---"---- */
+  0x0000,	/* pad */
+  0x0000,	/* pad */
+  0x0000,	/* pad */
+  0x0000,	/* pad */
+  0x0000,	/* pad */
+  0x0000	/* pad */
+};
+
+#define elf_arcV2_pic_PLT0_ENTRY_SIZE (2 * PLT_ENTRY_SIZE_V2/2)
+
+/* Contents of the subsequent entries in the pic plt for ARCv2.  */
+static const insn_hword elf_arcV2_pic_pltn_entry[PLT_ENTRY_SIZE_V2 / 2] =
+{
+  0x2730,	/* ld %r12, [%pc,func@got] */
+  0x7f8c,	/* ------ " " -------------- */
+  0x0000,	/* ------ " " -------------- */
+  0x0000,	/* ------ " " -------------- */
+  0x2021,	/* j.d [%r12] */
+  0x0300,	/* ------ " " -------------- */
+  0x240a,	/* mov %r12, %pcl */
+  0x1fc0	/* ------ " " -------------- */
+};
+
+#define elf_arcV2_pic_PLTN_ENTRY_SIZE (PLT_ENTRY_SIZE_V2/2)
+
+enum plt_reloc_symbol
+{
+  LAST_RELOC = 0,
+
+  SGOT = 1,
+
+  RELATIVE = (1 << 8),
+  MIDDLE_ENDIAN = (1 << 9)
+};
+
+#define IS_RELATIVE(S) ((S & RELATIVE) != 0)
+#define IS_MIDDLE_ENDIAN(S) ((S & MIDDLE_ENDIAN) != 0)
+#define SYM_ONLY(S) (S & 0xFF)
+
+struct plt_reloc
+{
+  bfd_vma	  offset;
+  bfd_vma	  size;
+  bfd_vma	  mask;
+  enum plt_reloc_symbol symbol;
+  bfd_vma	  addend;
+};
+
+struct plt_version_t
+{
+  const insn_hword *    entry;
+  const bfd_vma		entry_size;
+  const insn_hword *    elem;
+  const bfd_vma		elem_size;
+
+  struct plt_reloc entry_relocs[5];
+  struct plt_reloc elem_relocs[5];
+};
+
+
+#define PLT_DATA(NAME, ...) \
+  .entry = NAME##_plt0_entry, \
+  .entry_size = NAME##_PLT0_ENTRY_SIZE, \
+  .elem = NAME##_pltn_entry, \
+  .elem_size = NAME##_PLTN_ENTRY_SIZE
+
+struct plt_version_t plt_versions[] =
+{
+  {
+    PLT_DATA (elf_arcV2_pic),
+    .entry_relocs =
+    {
+      {4, 32, 0xFFFFFFFF, SGOT | RELATIVE | MIDDLE_ENDIAN, 4},
+      {12, 32, 0xFFFFFFFF, SGOT | RELATIVE | MIDDLE_ENDIAN, 8},
+      {20, 32, 0xFFFFFFFF, SGOT, 0},
+      {0, 0, 0, LAST_RELOC, 0}
+    },
+    .elem_relocs =
+    {
+      {4, 32, 0xFFFFFFFF, SGOT, 0},
+      {0, 0, 0, LAST_RELOC, 0}
+    }
+  }
+};
+#undef PLT_DATA
+
+static struct plt_version_t *
+arc_get_plt_version (void)
+{
+  return &(plt_versions[0]);
+}
+
+static bfd_vma
+add_symbol_to_plt (struct bfd_link_info *info)
+{
+  bfd *dynobj = (elf_hash_table (info))->dynobj;
+  struct dynamic_sections ds = arc_create_dynamic_sections (dynobj, info);
+  bfd_vma ret;
+
+  /* If this is the first .plt entry, make room for the special first entry.  */
+  if (ds.splt->size == 0)
+    ds.splt->size += 2 *
+		     (bfd_get_mach (dynobj) == bfd_mach_arc_arcv2
+		      ? PLT_ENTRY_SIZE_V2 : PLT_ENTRY_SIZE);
+
+  ret = ds.splt->size;
+
+  ds.splt->size += (bfd_get_mach (dynobj) == bfd_mach_arc_arcv2
+		    ? PLT_ENTRY_SIZE_V2
+		    : PLT_ENTRY_SIZE
+		   );
+  ds.sgotplt->size += 4;
+  ds.srelplt->size += sizeof (Elf32_External_Rela);
+
+  return ret;
+}
+
+#define PLT_DO_RELOCS_FOR_ENTRY(DS, RELOCS) \
+  plt_do_relocs_for_symbol (DS, RELOCS, 0, 0)
+
+static void
+plt_do_relocs_for_symbol (struct dynamic_sections *ds,
+			  struct plt_reloc *reloc,
+			  bfd_vma plt_offset,
+			  bfd_vma symbol_got_offset)
+{
+  while (SYM_ONLY (reloc->symbol) != LAST_RELOC)
+    {
+      bfd_vma relocation = 0;
+
+      switch (SYM_ONLY (reloc->symbol))
+	{
+	  case SGOT:
+		relocation =
+		    ds->sgotplt->output_section->vma +
+		    ds->sgotplt->output_offset + symbol_got_offset;
+		break;
+	}
+      relocation += reloc->addend;
+
+      relocation -= (IS_RELATIVE (reloc->symbol))
+	  ? ds->splt->output_section->vma + ds->splt->output_offset +
+	  plt_offset + reloc->offset : 0;
+
+      if (IS_MIDDLE_ENDIAN (reloc->symbol))
+	{
+	  relocation =
+	      ((relocation & 0xffff0000) >> 16) |
+	      ((relocation & 0xffff) << 16);
+	}
+
+      switch (reloc->size)
+	{
+	  case 32:
+	    bfd_put_32 (ds->splt->output_section->owner,
+			relocation,
+			ds->splt->contents + plt_offset + reloc->offset);
+	    break;
+	}
+
+      reloc = &(reloc[1]);	/* Jump to next relocation.  */
+    }
+}
+
+static void
+relocate_plt_for_symbol (struct bfd_link_info *info,
+			 struct elf_link_hash_entry *h)
+{
+  bfd * dynobj = elf_hash_table (info)->dynobj;
+  struct plt_version_t *plt_data = arc_get_plt_version ();
+  struct dynamic_sections ds = arc_create_dynamic_sections (dynobj, info);
+
+  bfd_vma plt_index = h->plt.offset / plt_data->elem_size;
+  bfd_vma got_offset = (plt_index + 3) * 4;
+
+  memcpy (ds.splt->contents + h->plt.offset, plt_data->elem,
+	  plt_data->elem_size * sizeof (insn_hword));
+  plt_do_relocs_for_symbol (&ds, plt_data->elem_relocs, h->plt.offset,
+			    got_offset);
+}
+
+static void
+relocate_plt_for_entry (struct bfd_link_info *info)
+{
+  bfd * dynobj = (elf_hash_table (info))->dynobj;
+  struct plt_version_t *plt_data = arc_get_plt_version ();
+  struct dynamic_sections ds = arc_create_dynamic_sections (dynobj, info);
+
+  memcpy (ds.splt->contents, plt_data->entry,
+	  plt_data->entry_size * sizeof (insn_hword));
+  PLT_DO_RELOCS_FOR_ENTRY (&ds, plt_data->entry_relocs);
+}
+
+
+/* Desc : Adjust a symbol defined by a dynamic object and referenced by a
+   regular object.  The current definition is in some section of the
+   dynamic object, but we're not including those sections.  We have to
+   change the definition to something the rest of the link can
+   understand.  */
+
+static bfd_boolean
+elf_arc_adjust_dynamic_symbol (struct bfd_link_info *info,
+			      struct elf_link_hash_entry *h)
+{
+  bfd *dynobj = (elf_hash_table (info))->dynobj;
+  struct dynamic_sections ds = arc_create_dynamic_sections (dynobj, info);
+
+  if (h->needs_plt == 1)
+    {
+      if (!bfd_link_pic (info) && !h->def_dynamic && !h->ref_dynamic)
+	{
+	  /* This case can occur if we saw a PLT32 reloc in an input
+	     file, but the symbol was never referred to by a dynamic
+	     object.  In such a case, we don't actually need to build
+	     a procedure linkage table, and we can just do a PC32
+	     reloc instead.  */
+	  BFD_ASSERT (h->needs_plt);
+	  return TRUE;
+	}
+
+      /* Make sure this symbol is output as a dynamic symbol.  */
+      if (h->dynindx == -1 && !h->forced_local
+	  && !bfd_elf_link_record_dynamic_symbol (info, h))
+	return FALSE;
+
+      if (bfd_link_pic (info) || WILL_CALL_FINISH_DYNAMIC_SYMBOL (1, 0, h))
+	{
+	  bfd_vma loc = add_symbol_to_plt (info);
+
+	  if (!bfd_link_pic (info) && !h->def_regular)
+	    {
+	      h->root.u.def.section = ds.splt;
+	      h->root.u.def.value = loc;
+	    }
+	  h->plt.offset = loc;
+	}
+    }
+  else
+    {
+      h->plt.offset = (bfd_vma) - 1;
+      h->needs_plt = 0;
+    }
+
+  return TRUE;
+}
+
+#define ADD_RELA(BFD, SECTION, OFFSET, SYM_IDX, TYPE, ADDEND) \
+{\
+  struct dynamic_sections ds = arc_create_dynamic_sections (output_bfd, info); \
+  bfd_byte * rloc = ds.srel##SECTION->contents + \
+    ((ds.srel##SECTION->reloc_count++) * sizeof (Elf32_External_Rela)); \
+  Elf_Internal_Rela rel; \
+  bfd_put_32 (output_bfd, (bfd_vma) 0, ds.s##SECTION->contents + OFFSET); \
+  rel.r_addend = ADDEND; \
+  rel.r_offset = (ds.s##SECTION)->output_section->vma + (ds.s##SECTION)->output_offset + OFFSET; \
+  rel.r_info = ELF32_R_INFO (SYM_IDX, TYPE); \
+  bfd_elf32_swap_reloca_out (BFD, &rel, rloc); \
+}
+
+/* Function :  elf_arc_finish_dynamic_symbol
+   Brief    :  Finish up dynamic symbol handling.  We set the
+  	     contents of various dynamic sections here.
+   Args     :  output_bfd :
+  	       info	  :
+  	       h	  :
+  	       sym	  :
+   Returns  : True/False as the return status.  */
+static bfd_boolean
+elf_arc_finish_dynamic_symbol (bfd * output_bfd,
+			       struct bfd_link_info *info,
+			       struct elf_link_hash_entry *h,
+			       Elf_Internal_Sym * sym)
+{
+  if (h->plt.offset != (bfd_vma) - 1)
+    relocate_plt_for_symbol (info, h);
+
+  if (h->got.offset != (bfd_vma) - 1)
+    {
+      if (bfd_link_pic (info) && (info->symbolic || h->dynindx == -1)
+	  && h->def_regular)
+	{
+	  ADD_RELA (output_bfd, got, h->got.offset, 0, R_ARC_RELATIVE, 0);
+	}
+      else
+	{
+	  ADD_RELA (output_bfd, got, h->got.offset, h->dynindx,
+		    R_ARC_GLOB_DAT, 0);
+	}
+    }
+
+  /* Mark _DYNAMIC and _GLOBAL_OFFSET_TABLE_ as absolute.  */
+  if (strcmp (h->root.root.string, "_DYNAMIC") == 0
+      || strcmp (h->root.root.string, "__DYNAMIC") == 0
+      || strcmp (h->root.root.string, "_GLOBAL_OFFSET_TABLE_") == 0)
+    sym->st_shndx = SHN_ABS;
+
+  return TRUE;
+}
+
+#define GET_SYMBOL_OR_SECTION(TAG, SYMBOL, SECTION) \
+  case TAG: \
+    if (SYMBOL != NULL) \
+      { \
+	h = elf_link_hash_lookup (elf_hash_table (info), SYMBOL, FALSE, FALSE, TRUE); \
+      } \
+    else if (SECTION != NULL) \
+      { \
+	s = bfd_get_section_by_name (output_bfd, SECTION); \
+	BFD_ASSERT (s != NULL); \
+	do_it = TRUE; \
+      } \
+    break;
+
+/* Function :  elf_arc_finish_dynamic_sections
+   Brief    :  Finish up the dynamic sections handling.
+   Args     :  output_bfd :
+  	       info	  :
+  	       h	  :
+  	       sym	  :
+   Returns  : True/False as the return status.  */
+static bfd_boolean
+elf_arc_finish_dynamic_sections (bfd * output_bfd, struct bfd_link_info *info)
+{
+  struct dynamic_sections ds = arc_create_dynamic_sections (output_bfd, info);
+  bfd *dynobj = (elf_hash_table (info))->dynobj;
+
+  if (ds.sdyn)
+    {
+      Elf32_External_Dyn *dyncon, *dynconend;
+
+      dyncon = (Elf32_External_Dyn *) ds.sdyn->contents;
+      dynconend =
+	  (Elf32_External_Dyn *) (ds.sdyn->contents + ds.sdyn->size);
+      for (; dyncon < dynconend; dyncon++)
+	{
+	  Elf_Internal_Dyn internal_dyn;
+	  bfd_boolean	  do_it = FALSE;
+
+	  struct elf_link_hash_entry *h = NULL;
+	  asection	 *s = NULL;
+
+	  bfd_elf32_swap_dyn_in (dynobj, dyncon, &internal_dyn);
+
+	  switch (internal_dyn.d_tag)
+	    {
+	      GET_SYMBOL_OR_SECTION (DT_INIT, "_init", NULL)
+	      GET_SYMBOL_OR_SECTION (DT_FINI, "_fini", NULL)
+	      GET_SYMBOL_OR_SECTION (DT_PLTGOT, NULL, ".plt")
+	      GET_SYMBOL_OR_SECTION (DT_JMPREL, NULL, ".rela.plt")
+	      GET_SYMBOL_OR_SECTION (DT_PLTRELSZ, NULL, ".rela.plt")
+	      GET_SYMBOL_OR_SECTION (DT_RELASZ, NULL, ".rela.plt")
+	      default:
+		break;
+	    }
+
+	  /* In case the dynamic symbols should be updated with a
+	     symbol.  */
+	  if (h != NULL
+	      && (h->root.type == bfd_link_hash_defined
+		  || h->root.type == bfd_link_hash_defweak)
+	      )
+	    {
+	      asection	     *asec_ptr;
+
+	      internal_dyn.d_un.d_val = h->root.u.def.value;
+	      asec_ptr = h->root.u.def.section;
+	      if (asec_ptr->output_section != NULL)
+		{
+		  internal_dyn.d_un.d_val +=
+		    (asec_ptr->output_section->vma +
+		     asec_ptr->output_offset);
+		}
+	      else
+		{
+		  /* The symbol is imported from another
+		     shared library and does not apply to this
+		     one.  */
+		  internal_dyn.d_un.d_val = 0;
+		}
+	      do_it = TRUE;
+	    }
+	  else if (s != NULL) /* With a section information.  */
+	    {
+	      switch (internal_dyn.d_tag)
+		{
+		  case DT_PLTGOT:
+		  case DT_JMPREL:
+		    internal_dyn.d_un.d_ptr = s->vma;
+		    do_it = TRUE;
+		    break;
+
+		  case DT_PLTRELSZ:
+		    internal_dyn.d_un.d_val = s->size;
+		    do_it = TRUE;
+		    break;
+
+		  case DT_RELASZ:
+		    internal_dyn.d_un.d_val -= s->size;
+		    do_it = TRUE;
+		    break;
+
+		  default:
+		    break;
+		}
+	    }
+
+	  if (do_it == TRUE)
+	    bfd_elf32_swap_dyn_out (output_bfd, &internal_dyn, dyncon);
+	}
+
+      if (ds.splt->size > 0)
+	{
+	  relocate_plt_for_entry (info);
+	}
+
+      elf_section_data (ds.srelplt->output_section)->this_hdr.sh_entsize = 0xc;
+    }
+
+  /* Fill in the first three entries in the global offset table.  */
+  if (ds.sgot)
+    {
+      if (ds.sgot->size > 0)
+	{
+	  if (ds.sdyn == NULL)
+	    bfd_put_32 (output_bfd, (bfd_vma) 0,
+			ds.sgotplt->contents);
+	  else
+	    bfd_put_32 (output_bfd,
+			ds.sdyn->output_section->vma + ds.sdyn->output_offset,
+			ds.sgotplt->contents);
+	  bfd_put_32 (output_bfd, (bfd_vma) 0, ds.sgotplt->contents + 4);
+	  bfd_put_32 (output_bfd, (bfd_vma) 0, ds.sgotplt->contents + 8);
+
+	  elf_section_data (ds.sgot->output_section)->this_hdr.sh_entsize = 4;
+	}
+    }
+
+  if (ds.srelgot
+      /* Check that the linker script has not dumped the .srelgot section.  */
+      && ds.srelgot->output_section
+      && elf_section_data (ds.srelgot->output_section))
+    {
+      /* TODO: Make it work even if I remove this.  */
+      elf_section_data (ds.srelgot->output_section)->this_hdr.sh_entsize = 0xc;
+    }
+
+  return TRUE;
+}
+
+#define ADD_DYNAMIC_SYMBOL(NAME, TAG) \
+  h =  elf_link_hash_lookup (elf_hash_table (info), NAME, FALSE, FALSE, FALSE); \
+  if ((h != NULL && (h->ref_regular || h->def_regular))) \
+    if (! _bfd_elf_add_dynamic_entry (info, TAG, 0)) \
+      return FALSE;
+
+/* Set the sizes of the dynamic sections.  */
+static bfd_boolean
+elf_arc_size_dynamic_sections (bfd * output_bfd, struct bfd_link_info *info)
+{
+  bfd *           dynobj;
+  asection *      s;
+  bfd_boolean	  relocs_exist;
+  bfd_boolean	  reltext_exist;
+  struct dynamic_sections ds = arc_create_dynamic_sections (output_bfd, info);
+
+  dynobj = (elf_hash_table (info))->dynobj;
+  BFD_ASSERT (dynobj != NULL);
+
+  if ((elf_hash_table (info))->dynamic_sections_created)
+    {
+      struct elf_link_hash_entry *h;
+
+      /* Set the contents of the .interp section to the interpreter.  */
+      if (!bfd_link_pic (info))
+	{
+	  s = bfd_get_section_by_name (dynobj, ".interp");
+	  BFD_ASSERT (s != NULL);
+	  s->size = sizeof ELF_DYNAMIC_INTERPRETER;
+	  s->contents = (unsigned char *) ELF_DYNAMIC_INTERPRETER;
+	}
+
+      /* Add some entries to the .dynamic section.  We fill in some of the
+         values later, in elf_bfd_final_link, but we must add the entries
+         now so that we know the final size of the .dynamic section.
+         Checking if the .init section is present.  We also create DT_INIT
+         and DT_FINI entries if the init_str has been changed by the user.  */
+
+      ADD_DYNAMIC_SYMBOL ("init", DT_INIT);
+      ADD_DYNAMIC_SYMBOL ("fini", DT_FINI);
+    }
+  else
+    {
+      /* We may have created entries in the .rela.got section.  However, if
+         we are not creating the dynamic sections, we will not actually
+         use these entries.  Reset the size of .rela.got, which will cause
+         it to get stripped from the output file below.  */
+      ds.srelgot->size = 0;
+    }
+
+  for (s = dynobj->sections; s != NULL; s = s->next)
+    {
+	bfd_boolean	is_dynamic_section = FALSE;
+
+	/* Skip any non dynamic section.  */
+	if (strstr (s->name, ".plt") != NULL
+	    || strstr (s->name, ".got") != NULL
+	  || strstr (s->name, ".rel") != NULL)
+	is_dynamic_section = TRUE;
+
+      /* Allocate memory for the section contents.  */
+      if (!is_dynamic_section)
+	continue;
+
+      s->contents = (bfd_byte *) bfd_alloc (dynobj, s->size);
+      if (s->contents == NULL && s->size != 0)
+	  return FALSE;
+
+      if (s->size == 0)
+	{
+	  s->flags |= SEC_EXCLUDE;
+	  continue;
+	}
+
+      if (strcmp (s->name, ".rela.plt") != 0)
+	{
+	  const char *outname = bfd_get_section_name (output_bfd,
+						      s->output_section);
+	  asection *target = bfd_get_section_by_name (output_bfd,
+						      outname + 4);
+
+	  relocs_exist = TRUE;
+	  if (target != NULL && target->size != 0
+	      && (target->flags & SEC_READONLY) != 0
+	      && (target->flags & SEC_ALLOC) != 0)
+	    reltext_exist = TRUE;
+	}
+    }
+
+  if (ds.sdyn)
+    {
+      if (ds.splt && ds.splt->size != 0)
+	if (!_bfd_elf_add_dynamic_entry (info, DT_PLTGOT, 0)
+	    || !_bfd_elf_add_dynamic_entry (info, DT_PLTRELSZ, 0)
+	    || !_bfd_elf_add_dynamic_entry (info, DT_PLTREL, DT_RELA)
+	    || !_bfd_elf_add_dynamic_entry (info, DT_JMPREL, 0)
+	   )
+	  return FALSE;
+
+      if (relocs_exist == TRUE)
+	if (!_bfd_elf_add_dynamic_entry (info, DT_RELA, 0)
+	    || !_bfd_elf_add_dynamic_entry (info, DT_RELASZ, 0)
+	    || !_bfd_elf_add_dynamic_entry (info, DT_RELENT,
+					    sizeof (Elf32_External_Rela))
+	   )
+	  return FALSE;
+
+      if (reltext_exist == TRUE)
+	if (!_bfd_elf_add_dynamic_entry (info, DT_TEXTREL, 0))
+	  return FALSE;
+    }
+
+  return TRUE;
+}
+
+
 #define TARGET_LITTLE_SYM   arc_elf32_le_vec
 #define TARGET_LITTLE_NAME  "elf32-littlearc"
-#define TARGET_BIG_SYM      arc_elf32_be_vec
-#define TARGET_BIG_NAME	    "elf32-bigarc"
-#define ELF_ARCH            bfd_arch_arc
-#define ELF_MACHINE_CODE    EM_ARC
-#define ELF_MAXPAGESIZE     0x1000
-
-#define elf_info_to_howto                   0
-#define elf_info_to_howto_rel               arc_info_to_howto_rel
-#define elf_backend_object_p                arc_elf_object_p
-#define elf_backend_final_write_processing  arc_elf_final_write_processing
+#define TARGET_BIG_SYM	    arc_elf32_be_vec
+#define TARGET_BIG_NAME     "elf32-bigarc"
+#define ELF_ARCH	    bfd_arch_arc
+#define ELF_MACHINE_CODE    EM_ARC_COMPACT
+#define ELF_MACHINE_ALT1    EM_ARC_COMPACT2
+#define ELF_MAXPAGESIZE     0x2000
+
+#define elf_info_to_howto_rel		     arc_info_to_howto_rel
+#define elf_backend_object_p		     arc_elf_object_p
+#define elf_backend_final_write_processing   arc_elf_final_write_processing
+
+#define elf_backend_relocate_section	     elf_arc_relocate_section
+#define elf_backend_check_relocs	     elf_arc_check_relocs
+#define elf_backend_create_dynamic_sections  _bfd_elf_create_dynamic_sections
+
+#define elf_backend_adjust_dynamic_symbol    elf_arc_adjust_dynamic_symbol
+#define elf_backend_finish_dynamic_symbol    elf_arc_finish_dynamic_symbol
+
+#define elf_backend_finish_dynamic_sections  elf_arc_finish_dynamic_sections
+#define elf_backend_size_dynamic_sections    elf_arc_size_dynamic_sections
+
+#define elf_backend_can_gc_sections	1
+#define elf_backend_want_got_plt	1
+#define elf_backend_plt_readonly	1
+#define elf_backend_want_plt_sym	0
+#define elf_backend_got_header_size	12
+
+#define elf_backend_may_use_rel_p	0
+#define elf_backend_may_use_rela_p	1
+#define elf_backend_default_use_rela_p	1
 
 #include "elf32-target.h"
diff --git a/bfd/elfxx-sparc.c b/bfd/elfxx-sparc.c
index db0d4f18..3e45461 100644
--- a/bfd/elfxx-sparc.c
+++ b/bfd/elfxx-sparc.c
@@ -3468,9 +3468,9 @@ _bfd_sparc_elf_relocate_section (bfd *output_bfd,
 		memset (&outrel, 0, sizeof outrel);
 	      /* h->dynindx may be -1 if the symbol was marked to
 		 become local.  */
-	      else if (h != NULL &&
-		       h->dynindx != -1
-		       && (! is_plt
+	      else if (h != NULL
+		       && h->dynindx != -1
+		       && (_bfd_sparc_elf_howto_table[r_type].pc_relative
 			   || !bfd_link_pic (info)
 			   || !SYMBOLIC_BIND (info, h)
 			   || !h->def_regular))
diff --git a/bfd/libbfd.h b/bfd/libbfd.h
index 03bb057..9ae9ba2 100644
--- a/bfd/libbfd.h
+++ b/bfd/libbfd.h
@@ -1663,8 +1663,71 @@ static const char *const bfd_reloc_code_real_names[] = { "@@uninitialized@@",
   "BFD_RELOC_SH_GOTOFFFUNCDESC",
   "BFD_RELOC_SH_GOTOFFFUNCDESC20",
   "BFD_RELOC_SH_FUNCDESC",
-  "BFD_RELOC_ARC_B22_PCREL",
-  "BFD_RELOC_ARC_B26",
+  "BFD_RELOC_ARC_NONE",
+  "BFD_RELOC_ARC_8",
+  "BFD_RELOC_ARC_16",
+  "BFD_RELOC_ARC_24",
+  "BFD_RELOC_ARC_32",
+  "BFD_RELOC_ARC_N8",
+  "BFD_RELOC_ARC_N16",
+  "BFD_RELOC_ARC_N24",
+  "BFD_RELOC_ARC_N32",
+  "BFD_RELOC_ARC_SDA",
+  "BFD_RELOC_ARC_SECTOFF",
+  "BFD_RELOC_ARC_S21H_PCREL",
+  "BFD_RELOC_ARC_S21W_PCREL",
+  "BFD_RELOC_ARC_S25H_PCREL",
+  "BFD_RELOC_ARC_S25W_PCREL",
+  "BFD_RELOC_ARC_SDA32",
+  "BFD_RELOC_ARC_SDA_LDST",
+  "BFD_RELOC_ARC_SDA_LDST1",
+  "BFD_RELOC_ARC_SDA_LDST2",
+  "BFD_RELOC_ARC_SDA16_LD",
+  "BFD_RELOC_ARC_SDA16_LD1",
+  "BFD_RELOC_ARC_SDA16_LD2",
+  "BFD_RELOC_ARC_S13_PCREL",
+  "BFD_RELOC_ARC_W",
+  "BFD_RELOC_ARC_32_ME",
+  "BFD_RELOC_ARC_32_ME_S",
+  "BFD_RELOC_ARC_N32_ME",
+  "BFD_RELOC_ARC_SECTOFF_ME",
+  "BFD_RELOC_ARC_SDA32_ME",
+  "BFD_RELOC_ARC_W_ME",
+  "BFD_RELOC_AC_SECTOFF_U8",
+  "BFD_RELOC_AC_SECTOFF_U8_1",
+  "BFD_RELOC_AC_SECTOFF_U8_2",
+  "BFD_RELOC_AC_SECTFOFF_S9",
+  "BFD_RELOC_AC_SECTFOFF_S9_1",
+  "BFD_RELOC_AC_SECTFOFF_S9_2",
+  "BFD_RELOC_ARC_SECTOFF_ME_1",
+  "BFD_RELOC_ARC_SECTOFF_ME_2",
+  "BFD_RELOC_ARC_SECTOFF_1",
+  "BFD_RELOC_ARC_SECTOFF_2",
+  "BFD_RELOC_ARC_SDA16_ST2",
+  "BFD_RELOC_ARC_PC32",
+  "BFD_RELOC_ARC_GOT32",
+  "BFD_RELOC_ARC_GOTPC32",
+  "BFD_RELOC_ARC_PLT32",
+  "BFD_RELOC_ARC_COPY",
+  "BFD_RELOC_ARC_GLOB_DAT",
+  "BFD_RELOC_ARC_JMP_SLOT",
+  "BFD_RELOC_ARC_RELATIVE",
+  "BFD_RELOC_ARC_GOTOFF",
+  "BFD_RELOC_ARC_GOTPC",
+  "BFD_RELOC_ARC_S21W_PCREL_PLT",
+  "BFD_RELOC_ARC_S25H_PCREL_PLT",
+  "BFD_RELOC_ARC_TLS_DTPMOD",
+  "BFD_RELOC_ARC_TLS_TPOFF",
+  "BFD_RELOC_ARC_TLS_GD_GOT",
+  "BFD_RELOC_ARC_TLS_GD_LD",
+  "BFD_RELOC_ARC_TLS_GD_CALL",
+  "BFD_RELOC_ARC_TLS_IE_GOT",
+  "BFD_RELOC_ARC_TLS_DTPOFF",
+  "BFD_RELOC_ARC_TLS_DTPOFF_S9",
+  "BFD_RELOC_ARC_TLS_LE_S9",
+  "BFD_RELOC_ARC_TLS_LE_32",
+  "BFD_RELOC_ARC_S25W_PCREL_PLT",
+  "BFD_RELOC_ARC_S21H_PCREL_PLT",
   "BFD_RELOC_BFIN_16_IMM",
   "BFD_RELOC_BFIN_16_HIGH",
   "BFD_RELOC_BFIN_4_PCREL",
diff --git a/bfd/reloc.c b/bfd/reloc.c
index 18ca7bb..886c63e 100644
--- a/bfd/reloc.c
+++ b/bfd/reloc.c
@@ -3515,18 +3515,137 @@ ENUMDOC
   Renesas / SuperH SH relocs.  Not all of these appear in object files.
 
 ENUM
-  BFD_RELOC_ARC_B22_PCREL
-ENUMDOC
-  ARC Cores relocs.
-  ARC 22 bit pc-relative branch.  The lowest two bits must be zero and are
-  not stored in the instruction.  The high 20 bits are installed in bits 26
-  through 7 of the instruction.
-ENUM
-  BFD_RELOC_ARC_B26
+  BFD_RELOC_ARC_NONE
+ENUMX
+  BFD_RELOC_ARC_8
+ENUMX
+  BFD_RELOC_ARC_16
+ENUMX
+  BFD_RELOC_ARC_24
+ENUMX
+  BFD_RELOC_ARC_32
+ENUMX
+  BFD_RELOC_ARC_N8
+ENUMX
+  BFD_RELOC_ARC_N16
+ENUMX
+  BFD_RELOC_ARC_N24
+ENUMX
+  BFD_RELOC_ARC_N32
+ENUMX
+  BFD_RELOC_ARC_SDA
+ENUMX
+  BFD_RELOC_ARC_SECTOFF
+ENUMX
+  BFD_RELOC_ARC_S21H_PCREL
+ENUMX
+  BFD_RELOC_ARC_S21W_PCREL
+ENUMX
+  BFD_RELOC_ARC_S25H_PCREL
+ENUMX
+  BFD_RELOC_ARC_S25W_PCREL
+ENUMX
+  BFD_RELOC_ARC_SDA32
+ENUMX
+  BFD_RELOC_ARC_SDA_LDST
+ENUMX
+  BFD_RELOC_ARC_SDA_LDST1
+ENUMX
+  BFD_RELOC_ARC_SDA_LDST2
+ENUMX
+  BFD_RELOC_ARC_SDA16_LD
+ENUMX
+  BFD_RELOC_ARC_SDA16_LD1
+ENUMX
+  BFD_RELOC_ARC_SDA16_LD2
+ENUMX
+  BFD_RELOC_ARC_S13_PCREL
+ENUMX
+  BFD_RELOC_ARC_W
+ENUMX
+  BFD_RELOC_ARC_32_ME
+ENUMX
+  BFD_RELOC_ARC_32_ME_S
+ENUMX
+  BFD_RELOC_ARC_N32_ME
+ENUMX
+  BFD_RELOC_ARC_SECTOFF_ME
+ENUMX
+  BFD_RELOC_ARC_SDA32_ME
+ENUMX
+  BFD_RELOC_ARC_W_ME
+ENUMX
+  BFD_RELOC_AC_SECTOFF_U8
+ENUMX
+  BFD_RELOC_AC_SECTOFF_U8_1
+ENUMX
+  BFD_RELOC_AC_SECTOFF_U8_2
+ENUMX
+  BFD_RELOC_AC_SECTFOFF_S9
+ENUMX
+  BFD_RELOC_AC_SECTFOFF_S9_1
+ENUMX
+  BFD_RELOC_AC_SECTFOFF_S9_2
+ENUMX
+  BFD_RELOC_ARC_SECTOFF_ME_1
+ENUMX
+  BFD_RELOC_ARC_SECTOFF_ME_2
+ENUMX
+  BFD_RELOC_ARC_SECTOFF_1
+ENUMX
+  BFD_RELOC_ARC_SECTOFF_2
+ENUMX
+  BFD_RELOC_ARC_SDA16_ST2
+ENUMX
+  BFD_RELOC_ARC_PC32
+ENUMX
+  BFD_RELOC_ARC_GOT32
+ENUMX
+  BFD_RELOC_ARC_GOTPC32
+ENUMX
+  BFD_RELOC_ARC_PLT32
+ENUMX
+  BFD_RELOC_ARC_COPY
+ENUMX
+  BFD_RELOC_ARC_GLOB_DAT
+ENUMX
+  BFD_RELOC_ARC_JMP_SLOT
+ENUMX
+  BFD_RELOC_ARC_RELATIVE
+ENUMX
+  BFD_RELOC_ARC_GOTOFF
+ENUMX
+  BFD_RELOC_ARC_GOTPC
+ENUMX
+  BFD_RELOC_ARC_S21W_PCREL_PLT
+ENUMX
+  BFD_RELOC_ARC_S25H_PCREL_PLT
+ENUMX
+  BFD_RELOC_ARC_TLS_DTPMOD
+ENUMX
+  BFD_RELOC_ARC_TLS_TPOFF
+ENUMX
+  BFD_RELOC_ARC_TLS_GD_GOT
+ENUMX
+  BFD_RELOC_ARC_TLS_GD_LD
+ENUMX
+  BFD_RELOC_ARC_TLS_GD_CALL
+ENUMX
+  BFD_RELOC_ARC_TLS_IE_GOT
+ENUMX
+  BFD_RELOC_ARC_TLS_DTPOFF
+ENUMX
+  BFD_RELOC_ARC_TLS_DTPOFF_S9
+ENUMX
+  BFD_RELOC_ARC_TLS_LE_S9
+ENUMX
+  BFD_RELOC_ARC_TLS_LE_32
+ENUMX
+  BFD_RELOC_ARC_S25W_PCREL_PLT
+ENUMX
+  BFD_RELOC_ARC_S21H_PCREL_PLT
 ENUMDOC
-  ARC 26 bit absolute branch.  The lowest two bits must be zero and are not
-  stored in the instruction.  The high 24 bits are installed in bits 23
-  through 0.
+  ARC relocs.
 
 ENUM
   BFD_RELOC_BFIN_16_IMM
diff --git a/binutils/ChangeLog b/binutils/ChangeLog
index 16ed7c4..e40926b 100644
--- a/binutils/ChangeLog
+++ b/binutils/ChangeLog
@@ -1,3 +1,16 @@
+2015-09-01  Claudiu Zissulescu  <claziss@synopsys.com>
+	    Cupertino Miranda  <cmiranda@synopsys.com>
+
+	* readelf.c (get_machine_name): Remove A5 reference. Add ARCompact
+	and ARCv2.
+	(get_machine_flags): Handle EM_ARCV2 and EM_ARCOMPACT.
+	(guess_is_rela): Likewise.
+	(dump_relocations): Likewise.
+	(is_32bit_abs_reloc): Likewise.
+	(is_16bit_abs_reloc): Likewise.
+	(is_none_reloc): Likewise.
+	* NEWS: Mention the new feature.
+
 2015-09-29  Andrew Stubbs  <ams@codesourcery.com>
 	    H.J. Lu  <hongjiu.lu@intel.com>
 
diff --git a/binutils/NEWS b/binutils/NEWS
index afcd7c9..fb36cf1 100644
--- a/binutils/NEWS
+++ b/binutils/NEWS
@@ -1,5 +1,7 @@
 -*- text -*-
 
+* Add support for the ARC EM/HS, and ARC600/700 architectures.
+
 * Extend objcopy --compress-debug-sections option to support
   --compress-debug-sections=[none|zlib|zlib-gnu|zlib-gabi] for ELF
   targets.
diff --git a/binutils/readelf.c b/binutils/readelf.c
index bbf5b02..e8c215d 100644
--- a/binutils/readelf.c
+++ b/binutils/readelf.c
@@ -728,6 +728,9 @@ guess_is_rela (unsigned int e_machine)
     case EM_ADAPTEVA_EPIPHANY:
     case EM_ALPHA:
     case EM_ALTERA_NIOS2:
+    case EM_ARC:
+    case EM_ARC_COMPACT:
+    case EM_ARC_COMPACT2:
     case EM_AVR:
     case EM_AVR_OLD:
     case EM_BLACKFIN:
@@ -1315,6 +1318,8 @@ dump_relocations (FILE * file,
 	  break;
 
 	case EM_ARC:
+	case EM_ARC_COMPACT:
+	case EM_ARC_COMPACT2:
 	  rtype = elf_arc_reloc_type (type);
 	  break;
 
@@ -2115,6 +2120,8 @@ get_machine_name (unsigned e_machine)
     case EM_SPARCV9:		return "Sparc v9";
     case EM_TRICORE:		return "Siemens Tricore";
     case EM_ARC:		return "ARC";
+    case EM_ARC_COMPACT:	return "ARCompact";
+    case EM_ARC_COMPACT2:	return "ARCv2";
     case EM_H8_300:		return "Renesas H8/300";
     case EM_H8_300H:		return "Renesas H8/300H";
     case EM_H8S:		return "Renesas H8S";
@@ -2182,7 +2189,6 @@ get_machine_name (unsigned e_machine)
     case EM_SCORE:		return "SUNPLUS S+Core";
     case EM_XSTORMY16:		return "Sanyo XStormy16 CPU core";
     case EM_OR1K:		return "OpenRISC 1000";
-    case EM_ARC_A5:		return "ARC International ARCompact processor";
     case EM_CRX:		return "National Semiconductor CRX microprocessor";
     case EM_ADAPTEVA_EPIPHANY:	return "Adapteva EPIPHANY";
     case EM_DLX:		return "OpenDLX";
@@ -2761,6 +2767,63 @@ get_machine_flags (unsigned e_flags, unsigned e_machine)
 	default:
 	  break;
 
+	case EM_ARC_COMPACT2:
+	  switch (e_flags & EF_ARC_MACH_MSK)
+	    {
+	    case EF_ARC_CPU_ARCV2EM:
+	      strcat (buf, ", ARC EM");
+	      break;
+	    case EF_ARC_CPU_ARCV2HS:
+	      strcat (buf, ", ARC HS");
+	      break;
+	    default:
+	      strcat (buf, ", unrecognized flag for ARCv2");
+	      break;
+	    }
+	  switch (e_flags & EF_ARC_OSABI_MSK)
+	    {
+	      /* Only upstream 3.9+ kernels will support ARCv2
+		 ISA.  */
+	    case E_ARC_OSABI_V3:
+	      strcat (buf, ", v3 no-legacy-syscalls ABI");
+	      break;
+	    }
+	  break;
+
+	case EM_ARC_COMPACT:
+	  switch (e_flags & EF_ARC_MACH_MSK)
+	    {
+	    case E_ARC_MACH_ARC600:
+	      strcat (buf, ", ARC 600");
+	      break;
+	    case E_ARC_MACH_ARC601:
+	      strcat (buf, ", ARC 601");
+	      break;
+	    case E_ARC_MACH_ARC700:
+	      strcat (buf, ", ARC 700");
+	      break;
+	    default:
+	      strcat (buf, ", Generic ARCompact");
+	      break;
+	    }
+	  switch (e_flags & EF_ARC_OSABI_MSK)
+	    {
+	    case E_ARC_OSABI_ORIG:
+	      strcat (buf, ", legacy syscall ABI");
+	      break;
+	    case E_ARC_OSABI_V2:
+	      /* For 3.2+ Linux kernels which use asm-generic
+		 hdrs.  */
+	      strcat (buf, ", v2 syscall ABI");
+	      break;
+	    case E_ARC_OSABI_V3:
+	      /* Upstream 3.9+ kernels which don't use any legacy
+		 syscalls.  */
+	      strcat (buf, ", v3 no-legacy-syscalls ABI");
+	      break;
+	    }
+	  break;
+
 	case EM_ARM:
 	  decode_ARM_machine_flags (e_flags, buf);
 	  break;
@@ -11302,6 +11365,9 @@ is_32bit_abs_reloc (unsigned int reloc_type)
       return reloc_type == 1; /* R_ALPHA_REFLONG.  */
     case EM_ARC:
       return reloc_type == 1; /* R_ARC_32.  */
+    case EM_ARC_COMPACT:
+    case EM_ARC_COMPACT2:
+      return reloc_type == 4; /* R_ARC_32.  */
     case EM_ARM:
       return reloc_type == 2; /* R_ARM_ABS32 */
     case EM_AVR_OLD:
@@ -11620,6 +11686,10 @@ is_16bit_abs_reloc (unsigned int reloc_type)
 {
   switch (elf_header.e_machine)
     {
+    case EM_ARC:
+    case EM_ARC_COMPACT:
+    case EM_ARC_COMPACT2:
+      return reloc_type == 2; /* R_ARC_16.  */
     case EM_AVR_OLD:
     case EM_AVR:
       return reloc_type == 4; /* R_AVR_16.  */
@@ -11690,6 +11760,9 @@ is_none_reloc (unsigned int reloc_type)
     case EM_ADAPTEVA_EPIPHANY:
     case EM_PPC:     /* R_PPC_NONE.  */
     case EM_PPC64:   /* R_PPC64_NONE.  */
+    case EM_ARC:     /* R_ARC_NONE.  */
+    case EM_ARC_COMPACT: /* R_ARC_NONE.  */
+    case EM_ARC_COMPACT2: /* R_ARC_NONE.  */
     case EM_ARM:     /* R_ARM_NONE.  */
     case EM_IA_64:   /* R_IA64_NONE.  */
     case EM_SH:      /* R_SH_NONE.  */
diff --git a/binutils/testsuite/binutils-all/objdump.exp b/binutils/testsuite/binutils-all/objdump.exp
index 62c91d8..c3cbb13 100644
--- a/binutils/testsuite/binutils-all/objdump.exp
+++ b/binutils/testsuite/binutils-all/objdump.exp
@@ -34,7 +34,7 @@ send_user "Version [binutil_version $OBJDUMP]"
 set got [binutils_run $OBJDUMP "$OBJDUMPFLAGS -i"]
 
 set cpus_expected [list]
-lappend cpus_expected aarch64 alpha arc arm cris
+lappend cpus_expected aarch64 alpha arc HS arm cris
 lappend cpus_expected d10v d30v fr30 fr500 fr550 h8 hppa i386 i860 i960 iamcu ip2022
 lappend cpus_expected m16c m32c m32r m68hc11 m68hc12 m68k m88k MCore mep c5 h1 MicroBlaze
 lappend cpus_expected mips mn10200 mn10300 ms1 msp MSP430 nds32 n1h_v3 ns32k
diff --git a/gas/ChangeLog b/gas/ChangeLog
index 2ece5c0..14b1647 100644
--- a/gas/ChangeLog
+++ b/gas/ChangeLog
@@ -1,3 +1,10 @@
+2015-10-07  Claudiu Zissulescu  <claziss@synopsys.com>
+
+        * config/tc-arc.c: Revamped file for ARC support.
+        * config/tc-arc.h: Likewise.
+        * doc/as.texinfo: Add new ARC options.
+        * doc/c-arc.texi: Likewise.
+
 2015-10-02  Renlin Li <renlin.li@arm.com>
 
 	* config/tc-aarch64.c (s_tlsdescadd): New.
diff --git a/gas/NEWS b/gas/NEWS
index 13a1911..03cfa64 100644
--- a/gas/NEWS
+++ b/gas/NEWS
@@ -1,5 +1,8 @@
 -*- text -*-
 
+* Add support for the ARC EM/HS, and ARC600/700 architectures.  Remove
+  assembler support for Argonaut RISC architectures.
+
 Changes in 2.26:
 
 * Symbol and label names can now be enclosed in double quotes (") which allows
diff --git a/gas/config/tc-arc.c b/gas/config/tc-arc.c
index 4806ed8..cc56797 100644
--- a/gas/config/tc-arc.c
+++ b/gas/config/tc-arc.c
@@ -1,6 +1,7 @@
 /* tc-arc.c -- Assembler for the ARC
    Copyright (C) 1994-2015 Free Software Foundation, Inc.
-   Contributed by Doug Evans (dje@cygnus.com).
+
+   Contributor: Claudiu Zissulescu <claziss@synopsys.com>
 
    This file is part of GAS, the GNU Assembler.
 
@@ -20,62 +21,57 @@
    02110-1301, USA.  */
 
 #include "as.h"
+#include "subsegs.h"
 #include "struc-symbol.h"
+#include "dwarf2dbg.h"
 #include "safe-ctype.h"
-#include "subsegs.h"
+
 #include "opcode/arc.h"
-#include "../opcodes/arc-ext.h"
 #include "elf/arc.h"
-#include "dwarf2dbg.h"
 
-const struct suffix_classes
-{
-  char *name;
-  int  len;
-} suffixclass[] =
-{
-  { "SUFFIX_COND|SUFFIX_FLAG",23 },
-  { "SUFFIX_FLAG", 11 },
-  { "SUFFIX_COND", 11 },
-  { "SUFFIX_NONE", 11 }
-};
+/* Defines section.  */
 
-#define MAXSUFFIXCLASS (sizeof (suffixclass) / sizeof (struct suffix_classes))
+#define MAX_FLAG_NAME_LENGHT 3
+#define MAX_INSN_FIXUPS      2
+#define MAX_CONSTR_STR       20
 
-const struct syntax_classes
-{
-  char *name;
-  int  len;
-  int  s_class;
-} syntaxclass[] =
-{
-  { "SYNTAX_3OP|OP1_MUST_BE_IMM", 26, SYNTAX_3OP|OP1_MUST_BE_IMM|SYNTAX_VALID },
-  { "OP1_MUST_BE_IMM|SYNTAX_3OP", 26, OP1_MUST_BE_IMM|SYNTAX_3OP|SYNTAX_VALID },
-  { "SYNTAX_2OP|OP1_IMM_IMPLIED", 26, SYNTAX_2OP|OP1_IMM_IMPLIED|SYNTAX_VALID },
-  { "OP1_IMM_IMPLIED|SYNTAX_2OP", 26, OP1_IMM_IMPLIED|SYNTAX_2OP|SYNTAX_VALID },
-  { "SYNTAX_3OP",                 10, SYNTAX_3OP|SYNTAX_VALID },
-  { "SYNTAX_2OP",                 10, SYNTAX_2OP|SYNTAX_VALID }
-};
+#ifdef DEBUG
+# define pr_debug(fmt, args...) fprintf (stderr, fmt, ##args)
+#else
+# define pr_debug(fmt, args...)
+#endif
+
+#define MAJOR_OPCODE(x)  (((x) & 0xF8000000) >> 27)
+#define SUB_OPCODE(x)	 (((x) & 0x003F0000) >> 16)
+#define LP_INSN(x)	 ((MAJOR_OPCODE (x) == 0x4) &&	\
+			  (SUB_OPCODE (x) == 0x28))
+
+/* Equal to MAX_PRECISION in atof-ieee.c.  */
+#define MAX_LITTLENUMS 6
+
+/* Macros section.  */
+
+#define regno(x)		((x) & 0x3F)
+#define is_ir_num(x)		(((x) & ~0x3F) == 0)
+#define is_code_density_p(op)   (((op)->subclass == CD1 || (op)->subclass == CD2))
+#define is_br_jmp_insn_p(op)    (((op)->class == BRANCH || (op)->class == JUMP))
+#define is_kernel_insn_p(op)    (((op)->class == KERNEL))
 
-#define MAXSYNTAXCLASS (sizeof (syntaxclass) / sizeof (struct syntax_classes))
+/* Generic assembler global variables which must be defined by all
+   targets.  */
 
-/* This array holds the chars that always start a comment.  If the
-   pre-processor is disabled, these aren't very useful.  */
+/* Characters which always start a comment.  */
 const char comment_chars[] = "#;";
 
-/* This array holds the chars that only start a comment at the beginning of
-   a line.  If the line seems to have the form '# 123 filename'
-   .line and .file directives will appear in the pre-processed output */
-/* Note that input_file.c hand checks for '#' at the beginning of the
-   first line of the input file.  This is because the compiler outputs
-   #NO_APP at the beginning of its output.  */
-/* Also note that comments started like this one will always
-   work if '/' isn't otherwise defined.  */
+/* Characters which start a comment at the beginning of a line.  */
 const char line_comment_chars[] = "#";
 
-const char line_separator_chars[] = "";
+/* Characters which may be used to separate multiple commands on a
+   single line.  */
+const char line_separator_chars[] = "`";
 
-/* Chars that can be used to separate mant from exp in floating point nums.  */
+/* Characters which are used to indicate an exponent in a floating
+   point number.  */
 const char EXP_CHARS[] = "eE";
 
 /* Chars that mean this number is a floating point constant
@@ -87,925 +83,949 @@ extern int target_big_endian;
 const char *arc_target_format = DEFAULT_TARGET_FORMAT;
 static int byte_order = DEFAULT_BYTE_ORDER;
 
-static segT arcext_section;
+extern int arc_get_mach (char *);
 
-/* One of bfd_mach_arc_n.  */
-static int arc_mach_type = bfd_mach_arc_6;
+/* Forward declaration.  */
+static void arc_lcomm (int);
+static void arc_option (int);
+static void arc_extra_reloc (int);
 
-/* Non-zero if the cpu type has been explicitly specified.  */
-static int mach_type_specified_p = 0;
+const pseudo_typeS md_pseudo_table[] =
+  {
+    /* Make sure that .word is 32 bits.  */
+    { "word", cons, 4 },
+
+    { "align",   s_align_bytes, 0 }, /* Defaulting is invalid (0).  */
+    { "lcomm",   arc_lcomm, 0 },
+    { "lcommon", arc_lcomm, 0 },
+    { "cpu",     arc_option, 0 },
 
-/* Non-zero if opcode tables have been initialized.
-   A .option command must appear before any instructions.  */
-static int cpu_tables_init_p = 0;
+    { "tls_gd_ld",   arc_extra_reloc, BFD_RELOC_ARC_TLS_GD_LD },
+    { "tls_gd_call", arc_extra_reloc, BFD_RELOC_ARC_TLS_GD_CALL },
+
+    { NULL, NULL, 0 }
+  };
 
-static struct hash_control *arc_suffix_hash = NULL;
-
 const char *md_shortopts = "";
 
 enum options
-{
-  OPTION_EB = OPTION_MD_BASE,
-  OPTION_EL,
-  OPTION_ARC5,
-  OPTION_ARC6,
-  OPTION_ARC7,
-  OPTION_ARC8,
-  OPTION_ARC
-};
+  {
+    OPTION_EB = OPTION_MD_BASE,
+    OPTION_EL,
+
+    OPTION_ARC600,
+    OPTION_ARC601,
+    OPTION_ARC700,
+    OPTION_ARCEM,
+    OPTION_ARCHS,
+
+    OPTION_MCPU,
+    OPTION_CD,
+
+    /* The following options are deprecated and provided here only for
+       compatibility reasons.  */
+    OPTION_USER_MODE,
+    OPTION_LD_EXT_MASK,
+    OPTION_SWAP,
+    OPTION_NORM,
+    OPTION_BARREL_SHIFT,
+    OPTION_MIN_MAX,
+    OPTION_NO_MPY,
+    OPTION_EA,
+    OPTION_MUL64,
+    OPTION_SIMD,
+    OPTION_SPFP,
+    OPTION_DPFP,
+    OPTION_XMAC_D16,
+    OPTION_XMAC_24,
+    OPTION_DSP_PACKA,
+    OPTION_CRC,
+    OPTION_DVBF,
+    OPTION_TELEPHONY,
+    OPTION_XYMEMORY,
+    OPTION_LOCK,
+    OPTION_SWAPE,
+    OPTION_RTSC,
+    OPTION_FPUDA
+  };
 
 struct option md_longopts[] =
-{
-  { "EB", no_argument, NULL, OPTION_EB },
-  { "EL", no_argument, NULL, OPTION_EL },
-  { "marc5", no_argument, NULL, OPTION_ARC5 },
-  { "pre-v6", no_argument, NULL, OPTION_ARC5 },
-  { "marc6", no_argument, NULL, OPTION_ARC6 },
-  { "marc7", no_argument, NULL, OPTION_ARC7 },
-  { "marc8", no_argument, NULL, OPTION_ARC8 },
-  { "marc", no_argument, NULL, OPTION_ARC },
-  { NULL, no_argument, NULL, 0 }
-};
-size_t md_longopts_size = sizeof (md_longopts);
+  {
+    { "EB",		no_argument,	   NULL, OPTION_EB },
+    { "EL",		no_argument,	   NULL, OPTION_EL },
+    { "mcpu",		required_argument, NULL, OPTION_MCPU },
+    { "mA6",		no_argument,	   NULL, OPTION_ARC600 },
+    { "mARC600",	no_argument,	   NULL, OPTION_ARC600 },
+    { "mARC601",	no_argument,	   NULL, OPTION_ARC601 },
+    { "mARC700",	no_argument,	   NULL, OPTION_ARC700 },
+    { "mA7",		no_argument,	   NULL, OPTION_ARC700 },
+    { "mEM",		no_argument,	   NULL, OPTION_ARCEM },
+    { "mHS",		no_argument,	   NULL, OPTION_ARCHS },
+    { "mcode-density",	no_argument,	   NULL, OPTION_CD },
+
+    /* The following options are deprecated and provided here only for
+       compatibility reasons.  */
+    { "mav2em", no_argument, NULL, OPTION_ARCEM },
+    { "mav2hs", no_argument, NULL, OPTION_ARCHS },
+    { "muser-mode-only", no_argument, NULL, OPTION_USER_MODE },
+    { "mld-extension-reg-mask", required_argument, NULL, OPTION_LD_EXT_MASK },
+    { "mswap", no_argument, NULL, OPTION_SWAP },
+    { "mnorm", no_argument, NULL, OPTION_NORM },
+    { "mbarrel-shifter", no_argument, NULL, OPTION_BARREL_SHIFT },
+    { "mbarrel_shifter", no_argument, NULL, OPTION_BARREL_SHIFT },
+    { "mmin-max", no_argument, NULL, OPTION_MIN_MAX },
+    { "mmin_max", no_argument, NULL, OPTION_MIN_MAX },
+    { "mno-mpy", no_argument, NULL, OPTION_NO_MPY },
+    { "mea", no_argument, NULL, OPTION_EA },
+    { "mEA", no_argument, NULL, OPTION_EA },
+    { "mmul64", no_argument, NULL, OPTION_MUL64 },
+    { "msimd", no_argument, NULL, OPTION_SIMD},
+    { "mspfp", no_argument, NULL, OPTION_SPFP},
+    { "mspfp-compact", no_argument, NULL, OPTION_SPFP},
+    { "mspfp_compact", no_argument, NULL, OPTION_SPFP},
+    { "mspfp-fast", no_argument, NULL, OPTION_SPFP},
+    { "mspfp_fast", no_argument, NULL, OPTION_SPFP},
+    { "mdpfp", no_argument, NULL, OPTION_DPFP},
+    { "mdpfp-compact", no_argument, NULL, OPTION_DPFP},
+    { "mdpfp_compact", no_argument, NULL, OPTION_DPFP},
+    { "mdpfp-fast", no_argument, NULL, OPTION_DPFP},
+    { "mdpfp_fast", no_argument, NULL, OPTION_DPFP},
+    { "mmac-d16", no_argument, NULL, OPTION_XMAC_D16},
+    { "mmac_d16", no_argument, NULL, OPTION_XMAC_D16},
+    { "mmac-24", no_argument, NULL, OPTION_XMAC_24},
+    { "mmac_24", no_argument, NULL, OPTION_XMAC_24},
+    { "mdsp-packa", no_argument, NULL, OPTION_DSP_PACKA},
+    { "mdsp_packa", no_argument, NULL, OPTION_DSP_PACKA},
+    { "mcrc", no_argument, NULL, OPTION_CRC},
+    { "mdvbf", no_argument, NULL, OPTION_DVBF},
+    { "mtelephony", no_argument, NULL, OPTION_TELEPHONY},
+    { "mxy", no_argument, NULL, OPTION_XYMEMORY},
+    { "mlock", no_argument, NULL, OPTION_LOCK},
+    { "mswape", no_argument, NULL, OPTION_SWAPE},
+    { "mrtsc", no_argument, NULL, OPTION_RTSC},
+    { "mfpuda", no_argument, NULL, OPTION_FPUDA},
+
+    { NULL,		no_argument, NULL, 0 }
+  };
 
-#define IS_SYMBOL_OPERAND(o) \
- ((o) == 'b' || (o) == 'c' || (o) == 's' || (o) == 'o' || (o) == 'O')
-
-struct arc_operand_value *get_ext_suffix (char *s);
+size_t md_longopts_size = sizeof (md_longopts);
 
-/* Invocation line includes a switch not recognized by the base assembler.
-   See if it's a processor-specific option.  */
+/* Local data and data types.  */
 
-int
-md_parse_option (int c, char *arg ATTRIBUTE_UNUSED)
-{
-  switch (c)
-    {
-    case OPTION_ARC5:
-      arc_mach_type = bfd_mach_arc_5;
-      break;
-    case OPTION_ARC:
-    case OPTION_ARC6:
-      arc_mach_type = bfd_mach_arc_6;
-      break;
-    case OPTION_ARC7:
-      arc_mach_type = bfd_mach_arc_7;
-      break;
-    case OPTION_ARC8:
-      arc_mach_type = bfd_mach_arc_8;
-      break;
-    case OPTION_EB:
-      byte_order = BIG_ENDIAN;
-      arc_target_format = "elf32-bigarc";
-      break;
-    case OPTION_EL:
-      byte_order = LITTLE_ENDIAN;
-      arc_target_format = "elf32-littlearc";
-      break;
-    default:
-      return 0;
-    }
-  return 1;
-}
+/* Used since new relocation types are introduced in this
+   file (DUMMY_RELOC_LITUSE_*).  */
+typedef int extended_bfd_reloc_code_real_type;
 
-void
-md_show_usage (FILE *stream)
+struct arc_fixup
 {
-  fprintf (stream, "\
-ARC Options:\n\
-  -marc[5|6|7|8]          select processor variant (default arc%d)\n\
-  -EB                     assemble code for a big endian cpu\n\
-  -EL                     assemble code for a little endian cpu\n", arc_mach_type + 5);
-}
+  expressionS exp;
 
-/* This function is called once, at assembler startup time.  It should
-   set up all the tables, etc. that the MD part of the assembler will need.
-   Opcode selection is deferred until later because we might see a .option
-   command.  */
+  extended_bfd_reloc_code_real_type reloc;
 
-void
-md_begin (void)
-{
-  /* The endianness can be chosen "at the factory".  */
-  target_big_endian = byte_order == BIG_ENDIAN;
+  /* index into arc_operands.  */
+  unsigned int opindex;
 
-  if (!bfd_set_arch_mach (stdoutput, bfd_arch_arc, arc_mach_type))
-    as_warn (_("could not set architecture and machine"));
+  /* PC-relative, used by internals fixups.  */
+  unsigned char pcrel;
 
-  /* This call is necessary because we need to initialize `arc_operand_map'
-     which may be needed before we see the first insn.  */
-  arc_opcode_init_tables (arc_get_opcode_mach (arc_mach_type,
-					       target_big_endian));
-}
+  /* TRUE if this fixup is for LIMM operand.  */
+  bfd_boolean islong;
+};
 
-/* Initialize the various opcode and operand tables.
-   MACH is one of bfd_mach_arc_xxx.  */
+struct arc_insn
+{
+  unsigned int insn;
+  int nfixups;
+  struct arc_fixup fixups[MAX_INSN_FIXUPS];
+  long limm;
+  bfd_boolean short_insn; /* Boolean value: TRUE if current insn is
+			     short.  */
+  bfd_boolean has_limm;   /* Boolean value: TRUE if limm field is
+			     valid.  */
+};
 
-static void
-init_opcode_tables (int mach)
+/* Structure to hold any last two instructions.  */
+static struct arc_last_insn
 {
-  int i;
-  char *last;
+  /* Saved instruction opcode.  */
+  const struct arc_opcode *opcode;
 
-  if ((arc_suffix_hash = hash_new ()) == NULL)
-    as_fatal (_("virtual memory exhausted"));
+  /* Boolean value: TRUE if current insn is short.  */
+  bfd_boolean has_limm;
 
-  if (!bfd_set_arch_mach (stdoutput, bfd_arch_arc, mach))
-    as_warn (_("could not set architecture and machine"));
+  /* Boolean value: TRUE if current insn has delay slot.  */
+  bfd_boolean has_delay_slot;
+} arc_last_insns[2];
 
-  /* This initializes a few things in arc-opc.c that we need.
-     This must be called before the various arc_xxx_supported fns.  */
-  arc_opcode_init_tables (arc_get_opcode_mach (mach, target_big_endian));
+/* The cpu for which we are generating code.  */
+static unsigned arc_target = ARC_OPCODE_BASE;
+static const char *arc_target_name = "<all>";
+static unsigned arc_features = 0x00;
 
-  /* Only put the first entry of each equivalently named suffix in the
-     table.  */
-  last = "";
-  for (i = 0; i < arc_suffixes_count; i++)
-    {
-      if (strcmp (arc_suffixes[i].name, last) != 0)
-	hash_insert (arc_suffix_hash, arc_suffixes[i].name, (void *) (arc_suffixes + i));
-      last = arc_suffixes[i].name;
-    }
+/* The default architecture.  */
+static int arc_mach_type = bfd_mach_arc_arcv2;
 
-  /* Since registers don't have a prefix, we put them in the symbol table so
-     they can't be used as symbols.  This also simplifies argument parsing as
-     we can let gas parse registers for us.  The recorded register number is
-     the address of the register's entry in arc_reg_names.
+/* Non-zero if the cpu type has been explicitly specified.  */
+static int mach_type_specified_p = 0;
 
-     If the register name is already in the table, then the existing
-     definition is assumed to be from an .ExtCoreRegister pseudo-op.  */
+/* The hash table of instruction opcodes.  */
+static struct hash_control *arc_opcode_hash;
 
-  for (i = 0; i < arc_reg_names_count; i++)
-    {
-      if (symbol_find (arc_reg_names[i].name))
-	continue;
-      /* Use symbol_create here instead of symbol_new so we don't try to
-	 output registers into the object file's symbol table.  */
-      symbol_table_insert (symbol_create (arc_reg_names[i].name,
-					  reg_section,
-					  (valueT) &arc_reg_names[i],
-					  &zero_address_frag));
-    }
+/* The hash table of register symbols.  */
+static struct hash_control *arc_reg_hash;
 
-  /* Tell `.option' it's too late.  */
-  cpu_tables_init_p = 1;
+/* A table of CPU names and opcode sets.  */
+static const struct cpu_type
+{
+  const char *name;
+  unsigned flags;
+  int mach;
+  unsigned eflags;
+  unsigned features;
 }
-
-/* Insert an operand value into an instruction.
-   If REG is non-NULL, it is a register number and ignore VAL.  */
-
-static arc_insn
-arc_insert_operand (arc_insn insn,
-		    const struct arc_operand *operand,
-		    int mods,
-		    const struct arc_operand_value *reg,
-		    offsetT val,
-		    char *file,
-		    unsigned int line)
+  cpu_types[] =
 {
-  if (operand->bits != 32)
-    {
-      long min, max;
-      offsetT test;
-
-      if ((operand->flags & ARC_OPERAND_SIGNED) != 0)
-	{
-	  if ((operand->flags & ARC_OPERAND_SIGNOPT) != 0)
-	    max = (1 << operand->bits) - 1;
-	  else
-	    max = (1 << (operand->bits - 1)) - 1;
-	  min = - (1 << (operand->bits - 1));
-	}
-      else
-	{
-	  max = (1 << operand->bits) - 1;
-	  min = 0;
-	}
+  { "arc600", ARC_OPCODE_ARC600,  bfd_mach_arc_arc600,
+    E_ARC_MACH_ARC600,  0x00},
+  { "arc700", ARC_OPCODE_ARC700,  bfd_mach_arc_arc700,
+    E_ARC_MACH_ARC700,  0x00},
+  { "arcem",  ARC_OPCODE_ARCv2EM, bfd_mach_arc_arcv2,
+    EF_ARC_CPU_ARCV2EM, 0x00},
+  { "archs",  ARC_OPCODE_ARCv2HS, bfd_mach_arc_arcv2,
+    EF_ARC_CPU_ARCV2HS, ARC_CD},
+  { "all",    ARC_OPCODE_BASE,    bfd_mach_arc_arcv2,
+    0x00, 0x00 },
+  { 0, 0, 0, 0, 0 }
+};
 
-      if ((operand->flags & ARC_OPERAND_NEGATIVE) != 0)
-	test = - val;
-      else
-	test = val;
+struct arc_flags
+{
+  /* Name of the parsed flag.  */
+  char name[MAX_FLAG_NAME_LENGHT+1];
 
-      if (test < (offsetT) min || test > (offsetT) max)
-	as_warn_value_out_of_range (_("operand"), test, (offsetT) min, (offsetT) max, file, line);
-    }
+  /* The code of the parsed flag.  Valid when is not zero.  */
+  unsigned char code;
+};
 
-  if (operand->insert)
+/* Used by the arc_reloc_op table.  Order is important.  */
+#define O_gotoff  O_md1     /* @gotoff relocation.  */
+#define O_gotpc   O_md2     /* @gotpc relocation.  */
+#define O_plt     O_md3     /* @plt relocation.  */
+#define O_sda     O_md4     /* @sda relocation.  */
+#define O_pcl     O_md5     /* @pcl relocation.  */
+#define O_tlsgd   O_md6     /* @tlsgd relocation.  */
+#define O_tlsie   O_md7     /* @tlsie relocation.  */
+#define O_tpoff9  O_md8     /* @tpoff9 relocation.  */
+#define O_tpoff   O_md9     /* @tpoff relocation.  */
+#define O_dtpoff9 O_md10    /* @dtpoff9 relocation.  */
+#define O_dtpoff  O_md11    /* @dtpoff relocation.  */
+#define O_last    O_dtpoff
+
+/* Used to define a bracket as operand in tokens.  */
+#define O_bracket O_md32
+
+/* Dummy relocation, to be sorted out.  */
+#define DUMMY_RELOC_ARC_ENTRY     (BFD_RELOC_UNUSED + 1)
+
+#define USER_RELOC_P(R) ((R) >= O_gotoff && (R) <= O_last)
+
+/* A table to map the spelling of a relocation operand into an appropriate
+   bfd_reloc_code_real_type type.  The table is assumed to be ordered such
+   that op-O_literal indexes into it.  */
+#define ARC_RELOC_TABLE(op)				\
+  (&arc_reloc_op[ ((!USER_RELOC_P (op))			\
+		   ? (abort (), 0)			\
+		   : (int) (op) - (int) O_gotoff) ])
+
+#define DEF(NAME, RELOC, REQ)				\
+  { #NAME, sizeof (#NAME)-1, O_##NAME, RELOC, REQ}
+
+static const struct arc_reloc_op_tag
+{
+  /* String to lookup.  */
+  const char *name;
+  /* Size of the string.  */
+  size_t length;
+  /* Which operator to use.  */
+  operatorT op;
+  extended_bfd_reloc_code_real_type reloc;
+  /* Allows complex relocation expression like identifier@reloc +
+     const.  */
+  unsigned int complex_expr : 1;
+}
+  arc_reloc_op[] =
     {
-      const char *errmsg;
+      DEF (gotoff,  BFD_RELOC_ARC_GOTOFF,	 1),
+      DEF (gotpc,   BFD_RELOC_ARC_GOTPC32,	 0),
+      DEF (plt,	    BFD_RELOC_ARC_PLT32,	 0),
+      DEF (sda,	    DUMMY_RELOC_ARC_ENTRY,	 1),
+      DEF (pcl,	    BFD_RELOC_ARC_PC32,		 1),
+      DEF (tlsgd,   BFD_RELOC_ARC_TLS_GD_GOT,	 0),
+      DEF (tlsie,   BFD_RELOC_ARC_TLS_IE_GOT,	 0),
+      DEF (tpoff9,  BFD_RELOC_ARC_TLS_LE_S9,	 0),
+      DEF (tpoff,   BFD_RELOC_ARC_TLS_LE_32,	 0),
+      DEF (dtpoff9, BFD_RELOC_ARC_TLS_DTPOFF_S9, 0),
+      DEF (dtpoff,  BFD_RELOC_ARC_TLS_DTPOFF,	 0),
+    };
 
-      errmsg = NULL;
-      insn = (*operand->insert) (insn, operand, mods, reg, (long) val, &errmsg);
-      if (errmsg != (const char *) NULL)
-	as_warn ("%s", errmsg);
+static const int arc_num_reloc_op
+= sizeof (arc_reloc_op) / sizeof (*arc_reloc_op);
+
+/* Flags to set in the elf header.  */
+static flagword [...]

[diff truncated at 100000 bytes]


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]