[LEDE-DEV] [RFC 3/5] toolchain: gcc: Add all patches from arc-2017.03 branch

Alexey Brodkin Alexey.Brodkin at synopsys.com
Fri Feb 10 11:40:58 PST 2017


The most recent release of GCC misses quite a lot of patches we need
for ARC. Some are fixes, some improvements but most of them are already in
GCC's master branch and will be a part of GCC v7.0.

Signed-off-by: Alexey Brodkin <Alexey.Brodkin at synopsys.com>
---
 .../0001-ARC-Add-SIMD-extensions-for-ARC-HS.patch  |  905 ++++++++
 .../6.3.0/0002-ARC-LIBGCC-Add-TLS-support.patch    |  144 ++
 .../patches/6.3.0/0003-ARC-Add-TLS-support.patch   | 1147 ++++++++++
 ...se-drsub-instructions-when-selecting-fpud.patch |  121 ++
 ...-FPUDA-code-gen-when-compiling-for-big-en.patch |  140 ++
 .../6.3.0/0006-ARC-Pass-mfpuda-to-assembler.patch  |   46 +
 ...Andrew-Burgess-andrew.burgess-embecosm.co.patch |  128 ++
 ...Andrew-Burgess-andrew.burgess-embecosm.co.patch |   78 +
 ...Joern-Rennecke-joern.rennecke-embecosm.co.patch |  701 +++++++
 ...Joern-Rennecke-joern.rennecke-embecosm.co.patch | 1059 ++++++++++
 ...Joern-Rennecke-joern.rennecke-embecosm.co.patch |  116 ++
 ...Andrew-Burgess-andrew.burgess-embecosm.co.patch |   59 +
 ...anted-match-for-sign-extend-16-bit-consta.patch |  170 ++
 .../6.3.0/0014-ARC-Fix-obsolete-constraint.patch   |   72 +
 ...FPX-NaN-within-optimized-floating-point-l.patch |  133 ++
 ...Andrew-Burgess-andrew.burgess-embecosm.co.patch |  123 ++
 .../0017-ARC-Add-new-ARCv2-instructions.patch      |  785 +++++++
 .../0018-Fix-warnings-update-source-code.patch     |   80 +
 ...019-ARC-Various-instruction-pattern-fixes.patch |   83 +
 .../6.3.0/0020-ARC-New-CPU-C-define-handler.patch  |  303 +++
 ...OFFPC-relocation-for-pc-relative-accesses.patch |  197 ++
 ...ption-handling-refurbish-multilib-support.patch | 2188 ++++++++++++++++++++
 ...023-ARC-Various-small-miscellaneous-fixes.patch |  243 +++
 ...Disable-compact-casesi-patterns-for-arcv2.patch |   50 +
 ...025-ARC-Add-support-for-QuarkSE-processor.patch |  429 ++++
 ...-libgcc-Add-support-for-QuarkSE-processor.patch |  441 ++++
 .../6.3.0/0027-ARC-libgcc-Fix-defines.patch        |  198 ++
 ...28-ARC-tests-Update-target-specific-tests.patch | 1103 ++++++++++
 .../gcc/patches/6.3.0/0029-ARC-Various-fixes.patch |   84 +
 .../0030-ARC-Add-simple-shift-rotate-ops.patch     |   68 +
 .../gcc/patches/6.3.0/0031-Fix-option-text.patch   |   44 +
 .../0032-ARC-Disable-tests-for-bare-metal.patch    |  133 ++
 .../0033-ARC-Update-INSN_LENGTH_ALIGNMENT.patch    |   34 +
 ...RC-Reimplement-exception-handling-support.patch |  523 +++++
 .../6.3.0/0035-ARC-Fix-mul32x16-patterns.patch     |   56 +
 .../6.3.0/0036-ARC-Cleanup-implementation.patch    |  201 ++
 .../6.3.0/0037-ARC-Refurbish-mul64-support.patch   |  126 ++
 toolchain/gcc/patches/6.3.0/0038-ARC-Fix-PIE.patch |  100 +
 .../0039-ARC-Generating-code-for-profiling.patch   | 2136 +++++++++++++++++++
 .../6.3.0/0040-ARC-Clean-up-arc-header-file.patch  |  501 +++++
 ...re-script-to-allow-non-uclibc-based-tripl.patch |   49 +
 ...0042-ARC-Fix-conditional-move-contstraint.patch |   32 +
 .../6.3.0/0043-Fix-tst_bitfield_tst-pattern.patch  |   66 +
 .../0044-ARC-Prohibit-negative-PIC-constants.patch |  105 +
 ...0045-ARC-Handle-complex-PIC-move-patterns.patch |  120 ++
 .../0046-ARC-Add-code-density-instructions.patch   |  300 +++
 .../6.3.0/0047-ARC-Code-size-modifications.patch   |  107 +
 .../0048-ARC-Save-restore-blink-when-in-ISR.patch  |   90 +
 ...ection-of-long-immediate-for-load-store-o.patch |   51 +
 ...-TP-register-when-building-for-bare-metal.patch |   58 +
 .../0051-ARC-Fix-divdf3-emulation-for-arcem.patch  |   53 +
 ...ic-context-save-restore-for-regular-inter.patch |  721 +++++++
 .../6.3.0/0053-ARC-Fast-interrupts-support.patch   |  575 +++++
 .../0054-ARC-Add-support-for-QuarkSE2-EM-cpu.patch |  269 +++
 ...ARC-Fix-move_double_src_operand-predicate.patch |   37 +
 .../6.3.0/0056-ARC-Remove-old-prof-patterns.patch  |  107 +
 ...-ARC-Update-mode_dependent_address_p-hook.patch |   40 +
 ...058-Changed-tests-to-verify-shared-option.patch |   56 +
 .../6.3.0/0059-ARC-DWARF-emitting-cleanup.patch    |   75 +
 .../0060-ARC-Use-long-jumps-for-CRT-calls.patch    |   36 +
 .../6.3.0/0061-ARC-Fix-typo-in-arc.opt.patch       |   35 +
 ...fine-SIZE_TYPE-and-PTRDIFF_TYPE-correctly.patch |   38 +
 ...CK-Hard-check-for-the-LP-size-constraints.patch |   38 +
 .../patches/6.3.0/0064-ARC-Fix-sub_n-pattern.patch |   29 +
 ...C-Make-mulsi-for-A700-pattern-commutative.patch |   29 +
 .../0066-ARC-Fix-LE-tests-for-nps400-variant.patch |  125 ++
 ...0067-ARC-Make-lp_count-reg-fix-for-ARC600.patch |   53 +
 ...support-for-advanced-mpy-mac-instructions.patch |  376 ++++
 .../6.3.0/0069-ARC-Fix-typo-dmpyh-pattern.patch    |   29 +
 ...ntiate-between-ARCv1-and-ARCv2-h-reg-clas.patch |  120 ++
 ...ntiate-between-ARCv1-and-ARCv2-h-reg-clas.patch |   89 +
 ...xtension-core-registers-to-be-used-for-ad.patch |   60 +
 ...-Make-D0-D1-double-regs-fix-when-not-used.patch |   33 +
 ...L-ACCH-registers-whenever-they-are-availa.patch |   36 +
 ...id-use-of-hard-registers-before-reg-alloc.patch |  236 +++
 ...ARC-Allow-r30-to-be-used-by-the-reg-alloc.patch |   52 +
 ...ARC-Cxx-Fix-calling-multiple-inheritances.patch |   55 +
 ...resses-can-use-long-immediate-for-offsets.patch |   94 +
 .../0079-ARC-Add-support-for-naked-functions.patch |  512 +++++
 ...rect-and-update-ARC-builtin-documentation.patch |  204 ++
 ...predicate-movv2hi-to-avoid-scaled-address.patch |   30 +
 ...non-commutative_binary_comparison-pattern.patch |   63 +
 ...-moving-stores-to-the-frame-before-the-st.patch |   86 +
 .../0084-ARC-LRA-Fix-tests-asm-constraints.patch   |   46 +
 ...ainst-frame_pointer_needed-in-arc_can_eli.patch |   35 +
 ...0086-ARC-Define-ADDITIONAL_REGISTER_NAMES.patch |   36 +
 ...RA-Avoid-emitting-COND_EXEC-during-expand.patch |  101 +
 .../0088-ARC-Clean-up-building-warnings.patch      |  154 ++
 ...ribute-naked-do-not-emit-return-instructi.patch |   64 +
 89 files changed, 21053 insertions(+)
 create mode 100644 toolchain/gcc/patches/6.3.0/0001-ARC-Add-SIMD-extensions-for-ARC-HS.patch
 create mode 100644 toolchain/gcc/patches/6.3.0/0002-ARC-LIBGCC-Add-TLS-support.patch
 create mode 100644 toolchain/gcc/patches/6.3.0/0003-ARC-Add-TLS-support.patch
 create mode 100644 toolchain/gcc/patches/6.3.0/0004-ARC-Don-t-use-drsub-instructions-when-selecting-fpud.patch
 create mode 100644 toolchain/gcc/patches/6.3.0/0005-ARC-Fix-FPX-FPUDA-code-gen-when-compiling-for-big-en.patch
 create mode 100644 toolchain/gcc/patches/6.3.0/0006-ARC-Pass-mfpuda-to-assembler.patch
 create mode 100644 toolchain/gcc/patches/6.3.0/0007-2016-04-28-Andrew-Burgess-andrew.burgess-embecosm.co.patch
 create mode 100644 toolchain/gcc/patches/6.3.0/0008-2016-04-28-Andrew-Burgess-andrew.burgess-embecosm.co.patch
 create mode 100644 toolchain/gcc/patches/6.3.0/0009-2016-04-28-Joern-Rennecke-joern.rennecke-embecosm.co.patch
 create mode 100644 toolchain/gcc/patches/6.3.0/0010-2016-04-28-Joern-Rennecke-joern.rennecke-embecosm.co.patch
 create mode 100644 toolchain/gcc/patches/6.3.0/0011-2016-04-28-Joern-Rennecke-joern.rennecke-embecosm.co.patch
 create mode 100644 toolchain/gcc/patches/6.3.0/0012-2016-04-28-Andrew-Burgess-andrew.burgess-embecosm.co.patch
 create mode 100644 toolchain/gcc/patches/6.3.0/0013-ARC-Fix-unwanted-match-for-sign-extend-16-bit-consta.patch
 create mode 100644 toolchain/gcc/patches/6.3.0/0014-ARC-Fix-obsolete-constraint.patch
 create mode 100644 toolchain/gcc/patches/6.3.0/0015-ARC-Handle-FPX-NaN-within-optimized-floating-point-l.patch
 create mode 100644 toolchain/gcc/patches/6.3.0/0016-2016-04-29-Andrew-Burgess-andrew.burgess-embecosm.co.patch
 create mode 100644 toolchain/gcc/patches/6.3.0/0017-ARC-Add-new-ARCv2-instructions.patch
 create mode 100644 toolchain/gcc/patches/6.3.0/0018-Fix-warnings-update-source-code.patch
 create mode 100644 toolchain/gcc/patches/6.3.0/0019-ARC-Various-instruction-pattern-fixes.patch
 create mode 100644 toolchain/gcc/patches/6.3.0/0020-ARC-New-CPU-C-define-handler.patch
 create mode 100644 toolchain/gcc/patches/6.3.0/0021-Use-GOTOFFPC-relocation-for-pc-relative-accesses.patch
 create mode 100644 toolchain/gcc/patches/6.3.0/0022-ARC-New-option-handling-refurbish-multilib-support.patch
 create mode 100644 toolchain/gcc/patches/6.3.0/0023-ARC-Various-small-miscellaneous-fixes.patch
 create mode 100644 toolchain/gcc/patches/6.3.0/0024-ARC-Disable-compact-casesi-patterns-for-arcv2.patch
 create mode 100644 toolchain/gcc/patches/6.3.0/0025-ARC-Add-support-for-QuarkSE-processor.patch
 create mode 100644 toolchain/gcc/patches/6.3.0/0026-ARC-libgcc-Add-support-for-QuarkSE-processor.patch
 create mode 100644 toolchain/gcc/patches/6.3.0/0027-ARC-libgcc-Fix-defines.patch
 create mode 100644 toolchain/gcc/patches/6.3.0/0028-ARC-tests-Update-target-specific-tests.patch
 create mode 100644 toolchain/gcc/patches/6.3.0/0029-ARC-Various-fixes.patch
 create mode 100644 toolchain/gcc/patches/6.3.0/0030-ARC-Add-simple-shift-rotate-ops.patch
 create mode 100644 toolchain/gcc/patches/6.3.0/0031-Fix-option-text.patch
 create mode 100644 toolchain/gcc/patches/6.3.0/0032-ARC-Disable-tests-for-bare-metal.patch
 create mode 100644 toolchain/gcc/patches/6.3.0/0033-ARC-Update-INSN_LENGTH_ALIGNMENT.patch
 create mode 100644 toolchain/gcc/patches/6.3.0/0034-ARC-Reimplement-exception-handling-support.patch
 create mode 100644 toolchain/gcc/patches/6.3.0/0035-ARC-Fix-mul32x16-patterns.patch
 create mode 100644 toolchain/gcc/patches/6.3.0/0036-ARC-Cleanup-implementation.patch
 create mode 100644 toolchain/gcc/patches/6.3.0/0037-ARC-Refurbish-mul64-support.patch
 create mode 100644 toolchain/gcc/patches/6.3.0/0038-ARC-Fix-PIE.patch
 create mode 100644 toolchain/gcc/patches/6.3.0/0039-ARC-Generating-code-for-profiling.patch
 create mode 100644 toolchain/gcc/patches/6.3.0/0040-ARC-Clean-up-arc-header-file.patch
 create mode 100644 toolchain/gcc/patches/6.3.0/0041-ARC-Configure-script-to-allow-non-uclibc-based-tripl.patch
 create mode 100644 toolchain/gcc/patches/6.3.0/0042-ARC-Fix-conditional-move-contstraint.patch
 create mode 100644 toolchain/gcc/patches/6.3.0/0043-Fix-tst_bitfield_tst-pattern.patch
 create mode 100644 toolchain/gcc/patches/6.3.0/0044-ARC-Prohibit-negative-PIC-constants.patch
 create mode 100644 toolchain/gcc/patches/6.3.0/0045-ARC-Handle-complex-PIC-move-patterns.patch
 create mode 100644 toolchain/gcc/patches/6.3.0/0046-ARC-Add-code-density-instructions.patch
 create mode 100644 toolchain/gcc/patches/6.3.0/0047-ARC-Code-size-modifications.patch
 create mode 100644 toolchain/gcc/patches/6.3.0/0048-ARC-Save-restore-blink-when-in-ISR.patch
 create mode 100644 toolchain/gcc/patches/6.3.0/0049-ARC-Fix-detection-of-long-immediate-for-load-store-o.patch
 create mode 100644 toolchain/gcc/patches/6.3.0/0050-ARC-Disable-TP-register-when-building-for-bare-metal.patch
 create mode 100644 toolchain/gcc/patches/6.3.0/0051-ARC-Fix-divdf3-emulation-for-arcem.patch
 create mode 100644 toolchain/gcc/patches/6.3.0/0052-ARC-Automatic-context-save-restore-for-regular-inter.patch
 create mode 100644 toolchain/gcc/patches/6.3.0/0053-ARC-Fast-interrupts-support.patch
 create mode 100644 toolchain/gcc/patches/6.3.0/0054-ARC-Add-support-for-QuarkSE2-EM-cpu.patch
 create mode 100644 toolchain/gcc/patches/6.3.0/0055-ARC-Fix-move_double_src_operand-predicate.patch
 create mode 100644 toolchain/gcc/patches/6.3.0/0056-ARC-Remove-old-prof-patterns.patch
 create mode 100644 toolchain/gcc/patches/6.3.0/0057-ARC-Update-mode_dependent_address_p-hook.patch
 create mode 100644 toolchain/gcc/patches/6.3.0/0058-Changed-tests-to-verify-shared-option.patch
 create mode 100644 toolchain/gcc/patches/6.3.0/0059-ARC-DWARF-emitting-cleanup.patch
 create mode 100644 toolchain/gcc/patches/6.3.0/0060-ARC-Use-long-jumps-for-CRT-calls.patch
 create mode 100644 toolchain/gcc/patches/6.3.0/0061-ARC-Fix-typo-in-arc.opt.patch
 create mode 100644 toolchain/gcc/patches/6.3.0/0062-ARC-define-SIZE_TYPE-and-PTRDIFF_TYPE-correctly.patch
 create mode 100644 toolchain/gcc/patches/6.3.0/0063-ARC-HACK-Hard-check-for-the-LP-size-constraints.patch
 create mode 100644 toolchain/gcc/patches/6.3.0/0064-ARC-Fix-sub_n-pattern.patch
 create mode 100644 toolchain/gcc/patches/6.3.0/0065-ARC-Make-mulsi-for-A700-pattern-commutative.patch
 create mode 100644 toolchain/gcc/patches/6.3.0/0066-ARC-Fix-LE-tests-for-nps400-variant.patch
 create mode 100644 toolchain/gcc/patches/6.3.0/0067-ARC-Make-lp_count-reg-fix-for-ARC600.patch
 create mode 100644 toolchain/gcc/patches/6.3.0/0068-ARC-Add-support-for-advanced-mpy-mac-instructions.patch
 create mode 100644 toolchain/gcc/patches/6.3.0/0069-ARC-Fix-typo-dmpyh-pattern.patch
 create mode 100644 toolchain/gcc/patches/6.3.0/0070-ARC-Differentiate-between-ARCv1-and-ARCv2-h-reg-clas.patch
 create mode 100644 toolchain/gcc/patches/6.3.0/0071-ARC-Differentiate-between-ARCv1-and-ARCv2-h-reg-clas.patch
 create mode 100644 toolchain/gcc/patches/6.3.0/0072-ARC-Allow-extension-core-registers-to-be-used-for-ad.patch
 create mode 100644 toolchain/gcc/patches/6.3.0/0073-ARC-Make-D0-D1-double-regs-fix-when-not-used.patch
 create mode 100644 toolchain/gcc/patches/6.3.0/0074-ARC-Use-ACCL-ACCH-registers-whenever-they-are-availa.patch
 create mode 100644 toolchain/gcc/patches/6.3.0/0075-ARC-Avoid-use-of-hard-registers-before-reg-alloc.patch
 create mode 100644 toolchain/gcc/patches/6.3.0/0076-ARC-Allow-r30-to-be-used-by-the-reg-alloc.patch
 create mode 100644 toolchain/gcc/patches/6.3.0/0077-ARC-Cxx-Fix-calling-multiple-inheritances.patch
 create mode 100644 toolchain/gcc/patches/6.3.0/0078-ARC-Addresses-can-use-long-immediate-for-offsets.patch
 create mode 100644 toolchain/gcc/patches/6.3.0/0079-ARC-Add-support-for-naked-functions.patch
 create mode 100644 toolchain/gcc/patches/6.3.0/0080-ARC-Correct-and-update-ARC-builtin-documentation.patch
 create mode 100644 toolchain/gcc/patches/6.3.0/0081-ARC-Change-predicate-movv2hi-to-avoid-scaled-address.patch
 create mode 100644 toolchain/gcc/patches/6.3.0/0082-ARC-Update-non-commutative_binary_comparison-pattern.patch
 create mode 100644 toolchain/gcc/patches/6.3.0/0083-ARC-Prevent-moving-stores-to-the-frame-before-the-st.patch
 create mode 100644 toolchain/gcc/patches/6.3.0/0084-ARC-LRA-Fix-tests-asm-constraints.patch
 create mode 100644 toolchain/gcc/patches/6.3.0/0085-ARC-Test-against-frame_pointer_needed-in-arc_can_eli.patch
 create mode 100644 toolchain/gcc/patches/6.3.0/0086-ARC-Define-ADDITIONAL_REGISTER_NAMES.patch
 create mode 100644 toolchain/gcc/patches/6.3.0/0087-ARC-LRA-Avoid-emitting-COND_EXEC-during-expand.patch
 create mode 100644 toolchain/gcc/patches/6.3.0/0088-ARC-Clean-up-building-warnings.patch
 create mode 100644 toolchain/gcc/patches/6.3.0/0089-ARC-FIX-Attribute-naked-do-not-emit-return-instructi.patch

diff --git a/toolchain/gcc/patches/6.3.0/0001-ARC-Add-SIMD-extensions-for-ARC-HS.patch b/toolchain/gcc/patches/6.3.0/0001-ARC-Add-SIMD-extensions-for-ARC-HS.patch
new file mode 100644
index 0000000..6b28a8d
--- /dev/null
+++ b/toolchain/gcc/patches/6.3.0/0001-ARC-Add-SIMD-extensions-for-ARC-HS.patch
@@ -0,0 +1,905 @@
+From d648963475c68b7193f206a79f26fbd61549c9fb Mon Sep 17 00:00:00 2001
+From: claziss <claziss at 138bc75d-0d04-0410-961f-82ee72b054a4>
+Date: Thu, 28 Apr 2016 09:53:13 +0000
+Subject: [PATCH 01/89] [ARC] Add SIMD extensions for ARC HS
+
+gcc/
+2016-04-28  Claudiu Zissulescu  <claziss at synopsys.com>
+
+	* config/arc/arc.c (arc_vector_mode_supported_p): Add support for
+	the new ARC HS SIMD instructions.
+	(arc_preferred_simd_mode): New function.
+	(arc_autovectorize_vector_sizes): Likewise.
+	(TARGET_VECTORIZE_PREFERRED_SIMD_MODE)
+	(TARGET_VECTORIZE_AUTOVECTORIZE_VECTOR_SIZES): Define.
+	(arc_init_reg_tables): Accept new ARC HS SIMD modes.
+	(arc_init_builtins): Add new SIMD builtin types.
+	(arc_split_move): Handle 64 bit vector moves.
+	* config/arc/arc.h (TARGET_PLUS_DMPY, TARGET_PLUS_MACD)
+	(TARGET_PLUS_QMACW): Define.
+	* config/arc/builtins.def (QMACH, QMACHU, QMPYH, QMPYHU, DMACH)
+	(DMACHU, DMPYH, DMPYHU, DMACWH, DMACWHU, VMAC2H, VMAC2HU, VMPY2H)
+	(VMPY2HU, VADDSUB2H, VSUBADD2H, VADDSUB, VSUBADD, VADDSUB4H)
+	(VSUBADD4H): New builtins.
+	* config/arc/simdext.md: Add new ARC HS SIMD instructions.
+	* testsuite/gcc.target/arc/builtin_simdarc.c: New file.
+
+git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@235551 138bc75d-0d04-0410-961f-82ee72b054a4
+---
+ gcc/ChangeLog                                  |  20 +
+ gcc/config/arc/arc.c                           | 112 ++++-
+ gcc/config/arc/arc.h                           |   6 +
+ gcc/config/arc/builtins.def                    |  27 ++
+ gcc/config/arc/simdext.md                      | 571 +++++++++++++++++++++++++
+ gcc/testsuite/gcc.target/arc/builtin_simdarc.c |  38 ++
+ 6 files changed, 767 insertions(+), 7 deletions(-)
+ create mode 100644 gcc/testsuite/gcc.target/arc/builtin_simdarc.c
+
+diff --git a/gcc/ChangeLog b/gcc/ChangeLog
+index 06ebfb1a548a..a88e2f2ff8be 100644
+--- a/gcc/ChangeLog
++++ b/gcc/ChangeLog
+@@ -1,3 +1,23 @@
++2016-04-28  Claudiu Zissulescu  <claziss at synopsys.com>
++
++	* config/arc/arc.c (arc_vector_mode_supported_p): Add support for
++	the new ARC HS SIMD instructions.
++	(arc_preferred_simd_mode): New function.
++	(arc_autovectorize_vector_sizes): Likewise.
++	(TARGET_VECTORIZE_PREFERRED_SIMD_MODE)
++	(TARGET_VECTORIZE_AUTOVECTORIZE_VECTOR_SIZES): Define.
++	(arc_init_reg_tables): Accept new ARC HS SIMD modes.
++	(arc_init_builtins): Add new SIMD builtin types.
++	(arc_split_move): Handle 64 bit vector moves.
++	* config/arc/arc.h (TARGET_PLUS_DMPY, TARGET_PLUS_MACD)
++	(TARGET_PLUS_QMACW): Define.
++	* config/arc/builtins.def (QMACH, QMACHU, QMPYH, QMPYHU, DMACH)
++	(DMACHU, DMPYH, DMPYHU, DMACWH, DMACWHU, VMAC2H, VMAC2HU, VMPY2H)
++	(VMPY2HU, VADDSUB2H, VSUBADD2H, VADDSUB, VSUBADD, VADDSUB4H)
++	(VSUBADD4H): New builtins.
++	* config/arc/simdext.md: Add new ARC HS SIMD instructions.
++	* testsuite/gcc.target/arc/builtin_simdarc.c: New file.
++
+ 2016-12-21  Release Manager
+ 
+ 	* GCC 6.3.0 released.
+diff --git a/gcc/config/arc/arc.c b/gcc/config/arc/arc.c
+index d60db502ef85..d120946a5f2f 100644
+--- a/gcc/config/arc/arc.c
++++ b/gcc/config/arc/arc.c
+@@ -247,16 +247,47 @@ static bool arc_use_by_pieces_infrastructure_p (unsigned HOST_WIDE_INT,
+ static bool
+ arc_vector_mode_supported_p (machine_mode mode)
+ {
+-  if (!TARGET_SIMD_SET)
+-    return false;
++  switch (mode)
++    {
++    case V2HImode:
++      return TARGET_PLUS_DMPY;
++    case V4HImode:
++    case V2SImode:
++      return TARGET_PLUS_QMACW;
++    case V4SImode:
++    case V8HImode:
++      return TARGET_SIMD_SET;
+ 
+-  if ((mode == V4SImode)
+-      || (mode == V8HImode))
+-    return true;
++    default:
++      return false;
++    }
++}
+ 
+-  return false;
++/* Implements target hook TARGET_VECTORIZE_PREFERRED_SIMD_MODE.  */
++
++static enum machine_mode
++arc_preferred_simd_mode (enum machine_mode mode)
++{
++  switch (mode)
++    {
++    case HImode:
++      return TARGET_PLUS_QMACW ? V4HImode : V2HImode;
++    case SImode:
++      return V2SImode;
++
++    default:
++      return word_mode;
++    }
+ }
+ 
++/* Implements target hook
++   TARGET_VECTORIZE_AUTOVECTORIZE_VECTOR_SIZES.  */
++
++static unsigned int
++arc_autovectorize_vector_sizes (void)
++{
++  return TARGET_PLUS_QMACW ? (8 | 4) : 0;
++}
+ 
+ /* TARGET_PRESERVE_RELOAD_P is still awaiting patch re-evaluation / review.  */
+ static bool arc_preserve_reload_p (rtx in) ATTRIBUTE_UNUSED;
+@@ -345,6 +376,12 @@ static void arc_finalize_pic (void);
+ #undef TARGET_VECTOR_MODE_SUPPORTED_P
+ #define TARGET_VECTOR_MODE_SUPPORTED_P arc_vector_mode_supported_p
+ 
++#undef TARGET_VECTORIZE_PREFERRED_SIMD_MODE
++#define TARGET_VECTORIZE_PREFERRED_SIMD_MODE arc_preferred_simd_mode
++
++#undef TARGET_VECTORIZE_AUTOVECTORIZE_VECTOR_SIZES
++#define TARGET_VECTORIZE_AUTOVECTORIZE_VECTOR_SIZES arc_autovectorize_vector_sizes
++
+ #undef TARGET_CAN_USE_DOLOOP_P
+ #define TARGET_CAN_USE_DOLOOP_P arc_can_use_doloop_p
+ 
+@@ -1214,7 +1251,12 @@ arc_init_reg_tables (void)
+ 	    arc_mode_class[i] = 0;
+ 	  break;
+ 	case MODE_VECTOR_INT:
+-	  arc_mode_class [i] = (1<< (int) V_MODE);
++	  if (GET_MODE_SIZE (m) == 4)
++	    arc_mode_class[i] = (1 << (int) S_MODE);
++	  else if (GET_MODE_SIZE (m) == 8)
++	    arc_mode_class[i] = (1 << (int) D_MODE);
++	  else
++	    arc_mode_class[i] = (1 << (int) V_MODE);
+ 	  break;
+ 	case MODE_CC:
+ 	default:
+@@ -5277,6 +5319,15 @@ arc_builtin_decl (unsigned id, bool initialize_p ATTRIBUTE_UNUSED)
+ static void
+ arc_init_builtins (void)
+ {
++  tree V4HI_type_node;
++  tree V2SI_type_node;
++  tree V2HI_type_node;
++
++  /* Vector types based on HS SIMD elements.  */
++  V4HI_type_node = build_vector_type_for_mode (intHI_type_node, V4HImode);
++  V2SI_type_node = build_vector_type_for_mode (intSI_type_node, V2SImode);
++  V2HI_type_node = build_vector_type_for_mode (intHI_type_node, V2HImode);
++
+   tree pcvoid_type_node
+     = build_pointer_type (build_qualified_type (void_type_node,
+ 						TYPE_QUAL_CONST));
+@@ -5341,6 +5392,28 @@ arc_init_builtins (void)
+   tree v8hi_ftype_v8hi
+     = build_function_type_list (V8HI_type_node, V8HI_type_node,
+ 				NULL_TREE);
++  /* ARCv2 SIMD types.  */
++  tree long_ftype_v4hi_v4hi
++    = build_function_type_list (long_long_integer_type_node,
++				V4HI_type_node,	V4HI_type_node, NULL_TREE);
++  tree int_ftype_v2hi_v2hi
++    = build_function_type_list (integer_type_node,
++				V2HI_type_node, V2HI_type_node, NULL_TREE);
++  tree v2si_ftype_v2hi_v2hi
++    = build_function_type_list (V2SI_type_node,
++				V2HI_type_node, V2HI_type_node, NULL_TREE);
++  tree v2hi_ftype_v2hi_v2hi
++    = build_function_type_list (V2HI_type_node,
++				V2HI_type_node, V2HI_type_node, NULL_TREE);
++  tree v2si_ftype_v2si_v2si
++    = build_function_type_list (V2SI_type_node,
++				V2SI_type_node, V2SI_type_node, NULL_TREE);
++  tree v4hi_ftype_v4hi_v4hi
++    = build_function_type_list (V4HI_type_node,
++				V4HI_type_node, V4HI_type_node, NULL_TREE);
++  tree long_ftype_v2si_v2hi
++    = build_function_type_list (long_long_integer_type_node,
++				V2SI_type_node, V2HI_type_node, NULL_TREE);
+ 
+   /* Add the builtins.  */
+ #define DEF_BUILTIN(NAME, N_ARGS, TYPE, ICODE, MASK)			\
+@@ -8706,6 +8779,31 @@ arc_split_move (rtx *operands)
+       return;
+     }
+ 
++  if (TARGET_PLUS_QMACW
++      && GET_CODE (operands[1]) == CONST_VECTOR)
++    {
++      HOST_WIDE_INT intval0, intval1;
++      if (GET_MODE (operands[1]) == V2SImode)
++	{
++	  intval0 = INTVAL (XVECEXP (operands[1], 0, 0));
++	  intval1 = INTVAL (XVECEXP (operands[1], 0, 1));
++	}
++      else
++	{
++	  intval1  = INTVAL (XVECEXP (operands[1], 0, 3)) << 16;
++	  intval1 |= INTVAL (XVECEXP (operands[1], 0, 2)) & 0xFFFF;
++	  intval0  = INTVAL (XVECEXP (operands[1], 0, 1)) << 16;
++	  intval0 |= INTVAL (XVECEXP (operands[1], 0, 0)) & 0xFFFF;
++	}
++      xop[0] = gen_rtx_REG (SImode, REGNO (operands[0]));
++      xop[3] = gen_rtx_REG (SImode, REGNO (operands[0]) + 1);
++      xop[2] = GEN_INT (trunc_int_for_mode (intval0, SImode));
++      xop[1] = GEN_INT (trunc_int_for_mode (intval1, SImode));
++      emit_move_insn (xop[0], xop[2]);
++      emit_move_insn (xop[3], xop[1]);
++      return;
++    }
++
+   for (i = 0; i < 2; i++)
+     {
+       if (MEM_P (operands[i]) && auto_inc_p (XEXP (operands[i], 0)))
+diff --git a/gcc/config/arc/arc.h b/gcc/config/arc/arc.h
+index 1c2a38d4acfc..5100a5b8f821 100644
+--- a/gcc/config/arc/arc.h
++++ b/gcc/config/arc/arc.h
+@@ -1724,6 +1724,12 @@ enum
+ /* Any multiplication feature macro.  */
+ #define TARGET_ANY_MPY						\
+   (TARGET_MPY || TARGET_MUL64_SET || TARGET_MULMAC_32BY16_SET)
++/* PLUS_DMPY feature macro.  */
++#define TARGET_PLUS_DMPY  ((arc_mpy_option > 6) && TARGET_HS)
++/* PLUS_MACD feature macro.  */
++#define TARGET_PLUS_MACD  ((arc_mpy_option > 7) && TARGET_HS)
++/* PLUS_QMACW feature macro.  */
++#define TARGET_PLUS_QMACW ((arc_mpy_option > 8) && TARGET_HS)
+ 
+ /* ARC600 and ARC601 feature macro.  */
+ #define TARGET_ARC600_FAMILY (TARGET_ARC600 || TARGET_ARC601)
+diff --git a/gcc/config/arc/builtins.def b/gcc/config/arc/builtins.def
+index 19be1d218520..8c71d30a459a 100644
+--- a/gcc/config/arc/builtins.def
++++ b/gcc/config/arc/builtins.def
+@@ -193,3 +193,30 @@ DEF_BUILTIN (VINTI, 1, void_ftype_int, vinti_insn, TARGET_SIMD_SET)
+ 
+ /* END SIMD marker.  */
+ DEF_BUILTIN (SIMD_END, 0, void_ftype_void, nothing, 0)
++
++/* ARCv2 SIMD instructions that use/clobber the accumulator reg.  */
++DEF_BUILTIN (QMACH,      2, long_ftype_v4hi_v4hi,   qmach,      TARGET_PLUS_QMACW)
++DEF_BUILTIN (QMACHU,     2, long_ftype_v4hi_v4hi,   qmachu,     TARGET_PLUS_QMACW)
++DEF_BUILTIN (QMPYH,      2, long_ftype_v4hi_v4hi,   qmpyh,      TARGET_PLUS_QMACW)
++DEF_BUILTIN (QMPYHU,     2, long_ftype_v4hi_v4hi,   qmpyhu,     TARGET_PLUS_QMACW)
++
++DEF_BUILTIN (DMACH,      2, int_ftype_v2hi_v2hi,    dmach,      TARGET_PLUS_DMPY)
++DEF_BUILTIN (DMACHU,     2, int_ftype_v2hi_v2hi,    dmachu,     TARGET_PLUS_DMPY)
++DEF_BUILTIN (DMPYH,      2, int_ftype_v2hi_v2hi,    dmpyh,      TARGET_PLUS_DMPY)
++DEF_BUILTIN (DMPYHU,     2, int_ftype_v2hi_v2hi,    dmpyhu,     TARGET_PLUS_DMPY)
++
++DEF_BUILTIN (DMACWH,     2, long_ftype_v2si_v2hi,   dmacwh,     TARGET_PLUS_QMACW)
++DEF_BUILTIN (DMACWHU,    2, long_ftype_v2si_v2hi,   dmacwhu,    TARGET_PLUS_QMACW)
++
++DEF_BUILTIN (VMAC2H,     2, v2si_ftype_v2hi_v2hi,   vmac2h,     TARGET_PLUS_MACD)
++DEF_BUILTIN (VMAC2HU,    2, v2si_ftype_v2hi_v2hi,   vmac2hu,    TARGET_PLUS_MACD)
++DEF_BUILTIN (VMPY2H,     2, v2si_ftype_v2hi_v2hi,   vmpy2h,     TARGET_PLUS_MACD)
++DEF_BUILTIN (VMPY2HU,    2, v2si_ftype_v2hi_v2hi,   vmpy2hu,    TARGET_PLUS_MACD)
++
++/* Combined add/sub HS SIMD instructions.  */
++DEF_BUILTIN (VADDSUB2H,  2, v2hi_ftype_v2hi_v2hi,   addsubv2hi3, TARGET_PLUS_DMPY)
++DEF_BUILTIN (VSUBADD2H,  2, v2hi_ftype_v2hi_v2hi,   subaddv2hi3, TARGET_PLUS_DMPY)
++DEF_BUILTIN (VADDSUB,    2, v2si_ftype_v2si_v2si,   addsubv2si3, TARGET_PLUS_QMACW)
++DEF_BUILTIN (VSUBADD,    2, v2si_ftype_v2si_v2si,   subaddv2si3, TARGET_PLUS_QMACW)
++DEF_BUILTIN (VADDSUB4H,  2, v4hi_ftype_v4hi_v4hi,   addsubv4hi3, TARGET_PLUS_QMACW)
++DEF_BUILTIN (VSUBADD4H,  2, v4hi_ftype_v4hi_v4hi,   subaddv4hi3, TARGET_PLUS_QMACW)
+diff --git a/gcc/config/arc/simdext.md b/gcc/config/arc/simdext.md
+index 9fd9d62e0483..51869e367726 100644
+--- a/gcc/config/arc/simdext.md
++++ b/gcc/config/arc/simdext.md
+@@ -1288,3 +1288,574 @@
+   [(set_attr "type" "simd_vcontrol")
+    (set_attr "length" "4")
+    (set_attr "cond" "nocond")])
++
++;; New ARCv2 SIMD extensions
++
++;;64-bit vectors of halwords and words
++(define_mode_iterator VWH [V4HI V2SI])
++
++;;double element vectors
++(define_mode_iterator VDV [V2HI V2SI])
++(define_mode_attr V_addsub [(V2HI "HI") (V2SI "SI")])
++(define_mode_attr V_addsub_suffix [(V2HI "2h") (V2SI "")])
++
++;;all vectors
++(define_mode_iterator VCT [V2HI V4HI V2SI])
++(define_mode_attr V_suffix [(V2HI "2h") (V4HI "4h") (V2SI "2")])
++
++;; Widening operations.
++(define_code_iterator SE [sign_extend zero_extend])
++(define_code_attr V_US [(sign_extend "s") (zero_extend "u")])
++(define_code_attr V_US_suffix [(sign_extend "") (zero_extend "u")])
++
++
++;; Move patterns
++(define_expand "movv2hi"
++  [(set (match_operand:V2HI 0 "move_dest_operand" "")
++	(match_operand:V2HI 1 "general_operand" ""))]
++  ""
++  "{
++    if (prepare_move_operands (operands, V2HImode))
++         DONE;
++   }")
++
++(define_insn_and_split "*movv2hi_insn"
++  [(set (match_operand:V2HI 0 "nonimmediate_operand" "=r,r,r,m")
++	(match_operand:V2HI 1 "general_operand"       "i,r,m,r"))]
++  "(register_operand (operands[0], V2HImode)
++    || register_operand (operands[1], V2HImode))"
++  "@
++   #
++   mov%? %0, %1
++   ld%U1%V1 %0,%1
++   st%U0%V0 %1,%0"
++  "reload_completed && GET_CODE (operands[1]) == CONST_VECTOR"
++  [(set (match_dup 0) (match_dup 2))]
++  {
++   HOST_WIDE_INT intval = INTVAL (XVECEXP (operands[1], 0, 1)) << 16;
++   intval |= INTVAL (XVECEXP (operands[1], 0, 0)) & 0xFFFF;
++
++   operands[0] = gen_rtx_REG (SImode, REGNO (operands[0]));
++   operands[2] = GEN_INT (trunc_int_for_mode (intval, SImode));
++  }
++  [(set_attr "type" "move,move,load,store")
++   (set_attr "predicable" "yes,yes,no,no")
++   (set_attr "iscompact"  "false,false,false,false")
++   ])
++
++(define_expand "movmisalignv2hi"
++ [(set (match_operand:V2HI 0 "general_operand" "")
++       (match_operand:V2HI 1 "general_operand" ""))]
++ ""
++{
++ if (!register_operand (operands[0], V2HImode)
++      && !register_operand (operands[1], V2HImode))
++    operands[1] = force_reg (V2HImode, operands[1]);
++})
++
++(define_expand "mov<mode>"
++  [(set (match_operand:VWH 0 "move_dest_operand" "")
++	(match_operand:VWH 1 "general_operand" ""))]
++  ""
++  "{
++    if (GET_CODE (operands[0]) == MEM)
++     operands[1] = force_reg (<MODE>mode, operands[1]);
++   }")
++
++(define_insn_and_split "*mov<mode>_insn"
++  [(set (match_operand:VWH 0 "move_dest_operand" "=r,r,r,m")
++	(match_operand:VWH 1 "general_operand"    "i,r,m,r"))]
++  "TARGET_PLUS_QMACW
++   && (register_operand (operands[0], <MODE>mode)
++       || register_operand (operands[1], <MODE>mode))"
++  "*
++{
++  switch (which_alternative)
++    {
++     default:
++       return \"#\";
++
++     case 1:
++       return \"vadd2 %0, %1, 0\";
++
++     case 2:
++       if (TARGET_LL64)
++         return \"ldd%U1%V1 %0,%1\";
++       return \"#\";
++
++     case 3:
++       if (TARGET_LL64)
++	   return \"std%U0%V0 %1,%0\";
++	 return \"#\";
++    }
++}"
++  "reload_completed"
++  [(const_int 0)]
++  {
++   arc_split_move (operands);
++   DONE;
++  }
++  [(set_attr "type" "move,move,load,store")
++   (set_attr "predicable" "yes,no,no,no")
++   (set_attr "iscompact"  "false,false,false,false")
++   ])
++
++(define_expand "movmisalign<mode>"
++ [(set (match_operand:VWH 0 "general_operand" "")
++       (match_operand:VWH 1 "general_operand" ""))]
++ ""
++{
++ if (!register_operand (operands[0], <MODE>mode)
++      && !register_operand (operands[1], <MODE>mode))
++    operands[1] = force_reg (<MODE>mode, operands[1]);
++})
++
++(define_insn "bswapv2hi2"
++  [(set (match_operand:V2HI 0 "register_operand" "=r,r")
++        (bswap:V2HI (match_operand:V2HI 1 "nonmemory_operand" "r,i")))]
++  "TARGET_V2 && TARGET_SWAP"
++  "swape %0, %1"
++  [(set_attr "length" "4,8")
++   (set_attr "type" "two_cycle_core")])
++
++;; Simple arithmetic insns
++(define_insn "add<mode>3"
++  [(set (match_operand:VCT 0 "register_operand"          "=r,r")
++	(plus:VCT (match_operand:VCT 1 "register_operand" "0,r")
++		  (match_operand:VCT 2 "register_operand" "r,r")))]
++  "TARGET_PLUS_DMPY"
++  "vadd<V_suffix>%? %0, %1, %2"
++  [(set_attr "length" "4")
++   (set_attr "type" "multi")
++   (set_attr "predicable" "yes,no")
++   (set_attr "cond" "canuse,nocond")])
++
++(define_insn "sub<mode>3"
++  [(set (match_operand:VCT 0 "register_operand"           "=r,r")
++	(minus:VCT (match_operand:VCT 1 "register_operand" "0,r")
++		   (match_operand:VCT 2 "register_operand" "r,r")))]
++  "TARGET_PLUS_DMPY"
++  "vsub<V_suffix>%? %0, %1, %2"
++  [(set_attr "length" "4")
++   (set_attr "type" "multi")
++   (set_attr "predicable" "yes,no")
++   (set_attr "cond" "canuse,nocond")])
++
++;; Combined arithmetic ops
++(define_insn "addsub<mode>3"
++  [(set (match_operand:VDV 0 "register_operand" "=r,r")
++	(vec_concat:VDV
++	 (plus:<V_addsub> (vec_select:<V_addsub> (match_operand:VDV 1 "register_operand" "0,r")
++						 (parallel [(const_int 0)]))
++			  (vec_select:<V_addsub> (match_operand:VDV 2 "register_operand" "r,r")
++						 (parallel [(const_int 0)])))
++	 (minus:<V_addsub> (vec_select:<V_addsub> (match_dup 1) (parallel [(const_int 1)]))
++			   (vec_select:<V_addsub> (match_dup 2) (parallel [(const_int 1)])))))]
++  "TARGET_PLUS_DMPY"
++  "vaddsub<V_addsub_suffix>%? %0, %1, %2"
++  [(set_attr "length" "4")
++   (set_attr "type" "multi")
++   (set_attr "predicable" "yes,no")
++   (set_attr "cond" "canuse,nocond")])
++
++(define_insn "subadd<mode>3"
++  [(set (match_operand:VDV 0 "register_operand" "=r,r")
++	(vec_concat:VDV
++	 (minus:<V_addsub> (vec_select:<V_addsub> (match_operand:VDV 1 "register_operand" "0,r")
++						  (parallel [(const_int 0)]))
++			   (vec_select:<V_addsub> (match_operand:VDV 2 "register_operand" "r,r")
++						  (parallel [(const_int 0)])))
++	 (plus:<V_addsub> (vec_select:<V_addsub> (match_dup 1) (parallel [(const_int 1)]))
++			  (vec_select:<V_addsub> (match_dup 2) (parallel [(const_int 1)])))))]
++  "TARGET_PLUS_DMPY"
++  "vsubadd<V_addsub_suffix>%? %0, %1, %2"
++  [(set_attr "length" "4")
++   (set_attr "type" "multi")
++   (set_attr "predicable" "yes,no")
++   (set_attr "cond" "canuse,nocond")])
++
++(define_insn "addsubv4hi3"
++  [(set (match_operand:V4HI 0 "even_register_operand" "=r,r")
++	(vec_concat:V4HI
++	 (vec_concat:V2HI
++	  (plus:HI (vec_select:HI (match_operand:V4HI 1 "even_register_operand" "0,r")
++				  (parallel [(const_int 0)]))
++		   (vec_select:HI (match_operand:V4HI 2 "even_register_operand" "r,r")
++				  (parallel [(const_int 0)])))
++	  (minus:HI (vec_select:HI (match_dup 1) (parallel [(const_int 1)]))
++		    (vec_select:HI (match_dup 2) (parallel [(const_int 1)]))))
++	 (vec_concat:V2HI
++	  (plus:HI (vec_select:HI (match_dup 1) (parallel [(const_int 2)]))
++		   (vec_select:HI (match_dup 2) (parallel [(const_int 2)])))
++	  (minus:HI (vec_select:HI (match_dup 1) (parallel [(const_int 3)]))
++		    (vec_select:HI (match_dup 2) (parallel [(const_int 3)]))))
++	 ))]
++  "TARGET_PLUS_QMACW"
++  "vaddsub4h%? %0, %1, %2"
++  [(set_attr "length" "4")
++   (set_attr "type" "multi")
++   (set_attr "predicable" "yes,no")
++   (set_attr "cond" "canuse,nocond")])
++
++(define_insn "subaddv4hi3"
++  [(set (match_operand:V4HI 0 "even_register_operand" "=r,r")
++	(vec_concat:V4HI
++	 (vec_concat:V2HI
++	  (minus:HI (vec_select:HI (match_operand:V4HI 1 "even_register_operand" "0,r")
++				   (parallel [(const_int 0)]))
++		    (vec_select:HI (match_operand:V4HI 2 "even_register_operand" "r,r")
++				  (parallel [(const_int 0)])))
++	  (plus:HI (vec_select:HI (match_dup 1) (parallel [(const_int 1)]))
++		   (vec_select:HI (match_dup 2) (parallel [(const_int 1)]))))
++	 (vec_concat:V2HI
++	  (minus:HI (vec_select:HI (match_dup 1) (parallel [(const_int 2)]))
++		    (vec_select:HI (match_dup 2) (parallel [(const_int 2)])))
++	  (plus:HI (vec_select:HI (match_dup 1) (parallel [(const_int 3)]))
++		   (vec_select:HI (match_dup 2) (parallel [(const_int 3)]))))
++	 ))]
++  "TARGET_PLUS_QMACW"
++  "vsubadd4h%? %0, %1, %2"
++  [(set_attr "length" "4")
++   (set_attr "type" "multi")
++   (set_attr "predicable" "yes,no")
++   (set_attr "cond" "canuse,nocond")])
++
++;; Multiplication
++(define_insn "dmpyh<V_US_suffix>"
++  [(set (match_operand:SI 0 "register_operand" "=r,r")
++	(plus:SI
++	 (mult:SI
++	  (SE:SI
++	   (vec_select:HI (match_operand:V2HI 1 "register_operand" "0,r")
++			  (parallel [(const_int 0)])))
++	  (SE:SI
++	   (vec_select:HI (match_operand:V2HI 2 "register_operand" "r,r")
++			  (parallel [(const_int 0)]))))
++	 (mult:SI
++	  (SE:SI (vec_select:HI (match_dup 1) (parallel [(const_int 1)])))
++	  (SE:SI (vec_select:HI (match_dup 2) (parallel [(const_int 1)]))))))
++   (set (reg:DI ARCV2_ACC)
++	(zero_extend:DI
++	 (plus:SI
++	  (mult:SI
++	   (SE:SI (vec_select:HI (match_dup 1) (parallel [(const_int 0)])))
++	   (SE:SI (vec_select:HI (match_dup 2) (parallel [(const_int 0)]))))
++	  (mult:SI
++	   (SE:SI (vec_select:HI (match_dup 1) (parallel [(const_int 1)])))
++	   (SE:SI (vec_select:HI (match_dup 2) (parallel [(const_int 1)])))))))]
++  "TARGET_PLUS_DMPY"
++  "dmpy<V_US_suffix>%? %0, %1, %2"
++  [(set_attr "length" "4")
++   (set_attr "type" "multi")
++   (set_attr "predicable" "yes,no")
++   (set_attr "cond" "canuse,nocond")])
++
++;; We can use dmac as well here.  To be investigated which version
++;; brings more.
++(define_expand "sdot_prodv2hi"
++  [(match_operand:SI 0 "register_operand" "")
++   (match_operand:V2HI 1 "register_operand" "")
++   (match_operand:V2HI 2 "register_operand" "")
++   (match_operand:SI 3 "register_operand" "")]
++  "TARGET_PLUS_DMPY"
++{
++ rtx t = gen_reg_rtx (SImode);
++ emit_insn (gen_dmpyh (t, operands[1], operands[2]));
++ emit_insn (gen_addsi3 (operands[0], operands[3], t));
++ DONE;
++})
++
++(define_expand "udot_prodv2hi"
++  [(match_operand:SI 0 "register_operand" "")
++   (match_operand:V2HI 1 "register_operand" "")
++   (match_operand:V2HI 2 "register_operand" "")
++   (match_operand:SI 3 "register_operand" "")]
++  "TARGET_PLUS_DMPY"
++{
++ rtx t = gen_reg_rtx (SImode);
++ emit_insn (gen_dmpyhu (t, operands[1], operands[2]));
++ emit_insn (gen_addsi3 (operands[0], operands[3], t));
++ DONE;
++})
++
++(define_insn "arc_vec_<V_US>mult_lo_v4hi"
++ [(set (match_operand:V2SI 0 "even_register_operand"                     "=r,r")
++       (mult:V2SI (SE:V2SI (vec_select:V2HI
++			    (match_operand:V4HI 1 "even_register_operand" "0,r")
++			    (parallel [(const_int 0) (const_int 1)])))
++		  (SE:V2SI (vec_select:V2HI
++			    (match_operand:V4HI 2 "even_register_operand" "r,r")
++			    (parallel [(const_int 0) (const_int 1)])))))
++  (set (reg:V2SI ARCV2_ACC)
++       (mult:V2SI (SE:V2SI (vec_select:V2HI (match_dup 1)
++					    (parallel [(const_int 0) (const_int 1)])))
++		  (SE:V2SI (vec_select:V2HI (match_dup 2)
++					    (parallel [(const_int 0) (const_int 1)])))))
++  ]
++  "TARGET_PLUS_MACD"
++  "vmpy2h<V_US_suffix>%? %0, %1, %2"
++  [(set_attr "length" "4")
++   (set_attr "type" "multi")
++   (set_attr "predicable" "yes,no")
++   (set_attr "cond" "canuse,nocond")])
++
++(define_insn "arc_vec_<V_US>multacc_lo_v4hi"
++  [(set (reg:V2SI ARCV2_ACC)
++	(mult:V2SI (SE:V2SI (vec_select:V2HI
++			     (match_operand:V4HI 0 "even_register_operand" "r")
++			     (parallel [(const_int 0) (const_int 1)])))
++		   (SE:V2SI (vec_select:V2HI
++			     (match_operand:V4HI 1 "even_register_operand" "r")
++			     (parallel [(const_int 0) (const_int 1)])))))
++  ]
++  "TARGET_PLUS_MACD"
++  "vmpy2h<V_US_suffix>%? 0, %0, %1"
++  [(set_attr "length" "4")
++   (set_attr "type" "multi")
++   (set_attr "predicable" "no")
++   (set_attr "cond" "nocond")])
++
++(define_expand "vec_widen_<V_US>mult_lo_v4hi"
++ [(set (match_operand:V2SI 0 "even_register_operand"                 "")
++       (mult:V2SI (SE:V2SI (vec_select:V2HI
++			    (match_operand:V4HI 1 "even_register_operand" "")
++			    (parallel [(const_int 0) (const_int 1)])))
++		  (SE:V2SI (vec_select:V2HI
++			    (match_operand:V4HI 2 "even_register_operand" "")
++			    (parallel [(const_int 0) (const_int 1)])))))]
++  "TARGET_PLUS_QMACW"
++  {
++     emit_insn (gen_arc_vec_<V_US>mult_lo_v4hi (operands[0],
++						operands[1],
++						operands[2]));
++     DONE;
++  }
++)
++
++(define_insn "arc_vec_<V_US>mult_hi_v4hi"
++ [(set (match_operand:V2SI 0 "even_register_operand"                     "=r,r")
++       (mult:V2SI (SE:V2SI (vec_select:V2HI
++			    (match_operand:V4HI 1 "even_register_operand" "0,r")
++			    (parallel [(const_int 2) (const_int 3)])))
++		  (SE:V2SI (vec_select:V2HI
++			    (match_operand:V4HI 2 "even_register_operand" "r,r")
++			    (parallel [(const_int 2) (const_int 3)])))))
++  (set (reg:V2SI ARCV2_ACC)
++       (mult:V2SI (SE:V2SI (vec_select:V2HI (match_dup 1)
++					    (parallel [(const_int 2) (const_int 3)])))
++		  (SE:V2SI (vec_select:V2HI (match_dup 2)
++					    (parallel [(const_int 2) (const_int 3)])))))
++  ]
++  "TARGET_PLUS_QMACW"
++  "vmpy2h<V_US_suffix>%? %0, %R1, %R2"
++  [(set_attr "length" "4")
++   (set_attr "type" "multi")
++   (set_attr "predicable" "yes,no")
++   (set_attr "cond" "canuse,nocond")])
++
++(define_expand "vec_widen_<V_US>mult_hi_v4hi"
++ [(set (match_operand:V2SI 0 "even_register_operand"                               "")
++       (mult:V2SI (SE:V2SI (vec_select:V2HI
++				     (match_operand:V4HI 1 "even_register_operand" "")
++				     (parallel [(const_int 2) (const_int 3)])))
++		  (SE:V2SI (vec_select:V2HI
++				     (match_operand:V4HI 2 "even_register_operand" "")
++				     (parallel [(const_int 2) (const_int 3)])))))]
++  "TARGET_PLUS_MACD"
++  {
++     emit_insn (gen_arc_vec_<V_US>mult_hi_v4hi (operands[0],
++						operands[1],
++						operands[2]));
++     DONE;
++  }
++)
++
++(define_insn "arc_vec_<V_US>mac_hi_v4hi"
++ [(set (match_operand:V2SI 0 "even_register_operand"                     "=r,r")
++       (plus:V2SI
++	(reg:V2SI ARCV2_ACC)
++	(mult:V2SI (SE:V2SI (vec_select:V2HI
++			     (match_operand:V4HI 1 "even_register_operand" "0,r")
++			     (parallel [(const_int 2) (const_int 3)])))
++		   (SE:V2SI (vec_select:V2HI
++			     (match_operand:V4HI 2 "even_register_operand" "r,r")
++			     (parallel [(const_int 2) (const_int 3)]))))))
++  (set (reg:V2SI ARCV2_ACC)
++       (plus:V2SI
++	(reg:V2SI ARCV2_ACC)
++	(mult:V2SI (SE:V2SI (vec_select:V2HI (match_dup 1)
++					     (parallel [(const_int 2) (const_int 3)])))
++		   (SE:V2SI (vec_select:V2HI (match_dup 2)
++					     (parallel [(const_int 2) (const_int 3)]))))))
++  ]
++  "TARGET_PLUS_MACD"
++  "vmac2h<V_US_suffix>%? %0, %R1, %R2"
++  [(set_attr "length" "4")
++   (set_attr "type" "multi")
++   (set_attr "predicable" "yes,no")
++   (set_attr "cond" "canuse,nocond")])
++
++;; Builtins
++(define_insn "dmach"
++  [(set (match_operand:SI 0 "register_operand" "=r,r")
++	(unspec:SI [(match_operand:V2HI 1 "register_operand" "0,r")
++		    (match_operand:V2HI 2 "register_operand" "r,r")
++		    (reg:DI ARCV2_ACC)]
++		   UNSPEC_ARC_DMACH))
++   (clobber (reg:DI ARCV2_ACC))]
++  "TARGET_PLUS_DMPY"
++  "dmach%? %0, %1, %2"
++  [(set_attr "length" "4")
++   (set_attr "type" "multi")
++   (set_attr "predicable" "yes,no")
++   (set_attr "cond" "canuse,nocond")])
++
++(define_insn "dmachu"
++  [(set (match_operand:SI 0 "register_operand" "=r,r")
++	(unspec:SI [(match_operand:V2HI 1 "register_operand" "0,r")
++		    (match_operand:V2HI 2 "register_operand" "r,r")
++		    (reg:DI ARCV2_ACC)]
++		   UNSPEC_ARC_DMACHU))
++   (clobber (reg:DI ARCV2_ACC))]
++  "TARGET_PLUS_DMPY"
++  "dmachu%? %0, %1, %2"
++  [(set_attr "length" "4")
++   (set_attr "type" "multi")
++   (set_attr "predicable" "yes,no")
++   (set_attr "cond" "canuse,nocond")])
++
++(define_insn "dmacwh"
++  [(set (match_operand:DI 0 "even_register_operand" "=r,r")
++	(unspec:DI [(match_operand:V2SI 1 "even_register_operand" "0,r")
++		    (match_operand:V2HI 2 "register_operand"      "r,r")
++		    (reg:DI ARCV2_ACC)]
++		   UNSPEC_ARC_DMACWH))
++   (clobber (reg:DI ARCV2_ACC))]
++  "TARGET_PLUS_QMACW"
++  "dmacwh%? %0, %1, %2"
++  [(set_attr "length" "4")
++   (set_attr "type" "multi")
++   (set_attr "predicable" "yes,no")
++   (set_attr "cond" "canuse,nocond")])
++
++(define_insn "dmacwhu"
++  [(set (match_operand:DI 0 "register_operand" "=r,r")
++	(unspec:DI [(match_operand:V2SI 1 "even_register_operand" "0,r")
++		    (match_operand:V2HI 2 "register_operand"      "r,r")
++		    (reg:DI ARCV2_ACC)]
++		   UNSPEC_ARC_DMACWHU))
++   (clobber (reg:DI ARCV2_ACC))]
++  "TARGET_PLUS_QMACW"
++  "dmacwhu%? %0, %1, %2"
++  [(set_attr "length" "4")
++   (set_attr "type" "multi")
++   (set_attr "predicable" "yes,no")
++   (set_attr "cond" "canuse,nocond")])
++
++(define_insn "vmac2h"
++  [(set (match_operand:V2SI 0 "even_register_operand" "=r,r")
++	(unspec:V2SI [(match_operand:V2HI 1 "register_operand" "0,r")
++		      (match_operand:V2HI 2 "register_operand" "r,r")
++		      (reg:DI ARCV2_ACC)]
++		     UNSPEC_ARC_VMAC2H))
++   (clobber (reg:DI ARCV2_ACC))]
++  "TARGET_PLUS_MACD"
++  "vmac2h%? %0, %1, %2"
++  [(set_attr "length" "4")
++   (set_attr "type" "multi")
++   (set_attr "predicable" "yes,no")
++   (set_attr "cond" "canuse,nocond")])
++
++(define_insn "vmac2hu"
++  [(set (match_operand:V2SI 0 "even_register_operand" "=r,r")
++	(unspec:V2SI [(match_operand:V2HI 1 "register_operand" "0,r")
++		      (match_operand:V2HI 2 "register_operand" "r,r")
++		      (reg:DI ARCV2_ACC)]
++		   UNSPEC_ARC_VMAC2HU))
++   (clobber (reg:DI ARCV2_ACC))]
++  "TARGET_PLUS_MACD"
++  "vmac2hu%? %0, %1, %2"
++  [(set_attr "length" "4")
++   (set_attr "type" "multi")
++   (set_attr "predicable" "yes,no")
++   (set_attr "cond" "canuse,nocond")])
++
++(define_insn "vmpy2h"
++  [(set (match_operand:V2SI 0 "even_register_operand" "=r,r")
++	(unspec:V2SI [(match_operand:V2HI 1 "register_operand" "0,r")
++		      (match_operand:V2HI 2 "register_operand" "r,r")]
++		     UNSPEC_ARC_VMPY2H))
++   (clobber (reg:DI ARCV2_ACC))]
++  "TARGET_PLUS_MACD"
++  "vmpy2h%? %0, %1, %2"
++  [(set_attr "length" "4")
++   (set_attr "type" "multi")
++   (set_attr "predicable" "yes,no")
++   (set_attr "cond" "canuse,nocond")])
++
++(define_insn "vmpy2hu"
++  [(set (match_operand:V2SI 0 "even_register_operand" "=r,r")
++	(unspec:V2SI [(match_operand:V2HI 1 "register_operand" "0,r")
++		      (match_operand:V2HI 2 "register_operand" "r,r")]
++		     UNSPEC_ARC_VMPY2HU))
++   (clobber (reg:DI ARCV2_ACC))]
++  "TARGET_PLUS_MACD"
++  "vmpy2hu%? %0, %1, %2"
++  [(set_attr "length" "4")
++   (set_attr "type" "multi")
++   (set_attr "predicable" "yes,no")
++   (set_attr "cond" "canuse,nocond")])
++
++(define_insn "qmach"
++  [(set (match_operand:DI 0 "even_register_operand" "=r,r")
++	(unspec:DI [(match_operand:V4HI 1 "even_register_operand" "0,r")
++		    (match_operand:V4HI 2 "even_register_operand" "r,r")
++		    (reg:DI ARCV2_ACC)]
++		     UNSPEC_ARC_QMACH))
++   (clobber (reg:DI ARCV2_ACC))]
++  "TARGET_PLUS_QMACW"
++  "qmach%? %0, %1, %2"
++  [(set_attr "length" "4")
++   (set_attr "type" "multi")
++   (set_attr "predicable" "yes,no")
++   (set_attr "cond" "canuse,nocond")])
++
++(define_insn "qmachu"
++  [(set (match_operand:DI 0 "even_register_operand" "=r,r")
++	(unspec:DI [(match_operand:V4HI 1 "even_register_operand" "0,r")
++		    (match_operand:V4HI 2 "even_register_operand" "r,r")
++		    (reg:DI ARCV2_ACC)]
++		   UNSPEC_ARC_QMACHU))
++   (clobber (reg:DI ARCV2_ACC))]
++  "TARGET_PLUS_QMACW"
++  "qmachu%? %0, %1, %2"
++  [(set_attr "length" "4")
++   (set_attr "type" "multi")
++   (set_attr "predicable" "yes,no")
++   (set_attr "cond" "canuse,nocond")])
++
++(define_insn "qmpyh"
++  [(set (match_operand:DI 0 "even_register_operand" "=r,r")
++	(unspec:DI [(match_operand:V4HI 1 "even_register_operand" "0,r")
++		    (match_operand:V4HI 2 "even_register_operand" "r,r")]
++		     UNSPEC_ARC_QMPYH))
++   (clobber (reg:DI ARCV2_ACC))]
++  "TARGET_PLUS_QMACW"
++  "qmpyh%? %0, %1, %2"
++  [(set_attr "length" "4")
++   (set_attr "type" "multi")
++   (set_attr "predicable" "yes,no")
++   (set_attr "cond" "canuse,nocond")])
++
++(define_insn "qmpyhu"
++  [(set (match_operand:DI 0 "even_register_operand" "=r,r")
++	(unspec:DI [(match_operand:V4HI 1 "even_register_operand" "0,r")
++		    (match_operand:V4HI 2 "even_register_operand" "r,r")]
++		   UNSPEC_ARC_QMPYHU))
++   (clobber (reg:DI ARCV2_ACC))]
++  "TARGET_PLUS_QMACW"
++  "qmpyhu%? %0, %1, %2"
++  [(set_attr "length" "4")
++   (set_attr "type" "multi")
++   (set_attr "predicable" "yes,no")
++   (set_attr "cond" "canuse,nocond")])
+diff --git a/gcc/testsuite/gcc.target/arc/builtin_simdarc.c b/gcc/testsuite/gcc.target/arc/builtin_simdarc.c
+new file mode 100644
+index 000000000000..68aae40ca58e
+--- /dev/null
++++ b/gcc/testsuite/gcc.target/arc/builtin_simdarc.c
+@@ -0,0 +1,38 @@
++/* { dg-do compile } */
++/* { dg-options "-mcpu=archs -O2 -Werror-implicit-function-declaration -mmpy-option=9" } */
++
++#define STEST(name, rettype, op1type, op2type)	\
++  rettype test_ ## name				\
++  (op1type a, op2type b)			\
++  {						\
++    return __builtin_arc_ ## name (a, b);	\
++  }
++
++typedef short v2hi __attribute__ ((vector_size (4)));
++typedef short v4hi __attribute__ ((vector_size (8)));
++typedef int   v2si __attribute__ ((vector_size (8)));
++
++STEST (qmach,  long long, v4hi, v4hi)
++STEST (qmachu, long long, v4hi, v4hi)
++STEST (qmpyh,  long long, v4hi, v4hi)
++STEST (qmpyhu, long long, v4hi, v4hi)
++
++STEST (dmach,  int, v2hi, v2hi)
++STEST (dmachu, int, v2hi, v2hi)
++STEST (dmpyh,  int, v2hi, v2hi)
++STEST (dmpyhu, int, v2hi, v2hi)
++
++STEST (dmacwh,  long, v2si, v2hi)
++STEST (dmacwhu, long, v2si, v2hi)
++
++STEST (vmac2h,  v2si, v2hi, v2hi)
++STEST (vmac2hu, v2si, v2hi, v2hi)
++STEST (vmpy2h,  v2si, v2hi, v2hi)
++STEST (vmpy2hu, v2si, v2hi, v2hi)
++
++STEST (vaddsub2h, v2hi, v2hi, v2hi)
++STEST (vsubadd2h, v2hi, v2hi, v2hi)
++STEST (vaddsub,   v2si, v2si, v2si)
++STEST (vsubadd,   v2si, v2si, v2si)
++STEST (vaddsub4h, v4hi, v4hi, v4hi)
++STEST (vsubadd4h, v4hi, v4hi, v4hi)
+-- 
+2.7.4
+
diff --git a/toolchain/gcc/patches/6.3.0/0002-ARC-LIBGCC-Add-TLS-support.patch b/toolchain/gcc/patches/6.3.0/0002-ARC-LIBGCC-Add-TLS-support.patch
new file mode 100644
index 0000000..332014f
--- /dev/null
+++ b/toolchain/gcc/patches/6.3.0/0002-ARC-LIBGCC-Add-TLS-support.patch
@@ -0,0 +1,144 @@
+From 37ceb52d577de40f4497bd51baa328b9c1a7a860 Mon Sep 17 00:00:00 2001
+From: claziss <claziss at 138bc75d-0d04-0410-961f-82ee72b054a4>
+Date: Thu, 28 Apr 2016 11:53:34 +0000
+Subject: [PATCH 02/89] [ARC/LIBGCC] Add TLS support.
+
+libgcc/
+2016-04-28  Claudiu Zissulescu  <claziss at synopsys.com>
+	    Joern Rennecke  <joern.rennecke at embecosm.com>
+
+	* config/arc/crttls.S: New file.
+	* config/arc/t-arc: New rule.
+	* config.host (arc*-*-elf*, arc*-*-linux*): Add crttls.o.
+
+git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@235558 138bc75d-0d04-0410-961f-82ee72b054a4
+---
+ libgcc/ChangeLog           |  7 +++++
+ libgcc/config.host         |  2 ++
+ libgcc/config/arc/crttls.S | 67 ++++++++++++++++++++++++++++++++++++++++++++++
+ libgcc/config/arc/t-arc    |  3 +++
+ 4 files changed, 79 insertions(+)
+ create mode 100644 libgcc/config/arc/crttls.S
+
+diff --git a/libgcc/ChangeLog b/libgcc/ChangeLog
+index 8e5e308c7ddc..0993d6226cd2 100644
+--- a/libgcc/ChangeLog
++++ b/libgcc/ChangeLog
+@@ -1,3 +1,10 @@
++2016-04-28  Claudiu Zissulescu  <claziss at synopsys.com>
++	    Joern Rennecke  <joern.rennecke at embecosm.com>
++
++	* config/arc/crttls.S: New file.
++	* config/arc/t-arc: New rule.
++	* config.host (arc*-*-elf*, arc*-*-linux*): Add crttls.o.
++
+ 2016-12-21  Release Manager
+ 
+ 	* GCC 6.3.0 released.
+diff --git a/libgcc/config.host b/libgcc/config.host
+index 124f2ceaefda..4e02765fce74 100644
+--- a/libgcc/config.host
++++ b/libgcc/config.host
+@@ -367,10 +367,12 @@ alpha*-dec-*vms*)
+ arc*-*-elf*)
+ 	tmake_file="arc/t-arc-newlib arc/t-arc"
+ 	extra_parts="crti.o crtn.o crtend.o crtbegin.o crtendS.o crtbeginS.o libgmon.a crtg.o crtgend.o"
++	extra_parts="${extra_parts} crttls.o"
+ 	;;
+ arc*-*-linux-uclibc*)
+ 	tmake_file="${tmake_file} t-slibgcc-libgcc t-slibgcc-nolc-override arc/t-arc700-uClibc arc/t-arc"
+ 	extra_parts="crti.o crtn.o crtend.o crtbegin.o crtendS.o crtbeginS.o libgmon.a crtg.o crtgend.o"
++	extra_parts="${extra_parts} crttls.o"
+ 	;;
+ arm-wrs-vxworks)
+ 	tmake_file="$tmake_file arm/t-arm arm/t-elf t-softfp-sfdf t-softfp-excl arm/t-softfp t-softfp"
+diff --git a/libgcc/config/arc/crttls.S b/libgcc/config/arc/crttls.S
+new file mode 100644
+index 000000000000..512c1df53c02
+--- /dev/null
++++ b/libgcc/config/arc/crttls.S
+@@ -0,0 +1,67 @@
++; newlib tls glue code for Synopsys DesignWare ARC cpu.
++
++/* Copyright (C) 2016 Free Software Foundation, Inc.
++   Contributor: Joern Rennecke <joern.rennecke at embecosm.com>
++		on behalf of Synopsys Inc.
++
++This file is part of GCC.
++
++GCC is free software; you can redistribute it and/or modify it under
++the terms of the GNU General Public License as published by the Free
++Software Foundation; either version 3, or (at your option) any later
++version.
++
++GCC is distributed in the hope that it will be useful, but WITHOUT ANY
++WARRANTY; without even the implied warranty of MERCHANTABILITY or
++FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
++for more details.
++
++Under Section 7 of GPL version 3, you are granted additional
++permissions described in the GCC Runtime Library Exception, version
++3.1, as published by the Free Software Foundation.
++
++You should have received a copy of the GNU General Public License and
++a copy of the GCC Runtime Library Exception along with this program;
++see the files COPYING3 and COPYING.RUNTIME respectively.  If not, see
++<http://www.gnu.org/licenses/>.  */
++
++/* As a special exception, if you link this library with other files,
++   some of which are compiled with GCC, to produce an executable,
++   this library does not by itself cause the resulting executable
++   to be covered by the GNU General Public License.
++   This exception does not however invalidate any other reasons why
++   the executable file might be covered by the GNU General Public License.  */
++
++
++#if (__ARC_TLS_REGNO__ != -1)
++ /* ANSI concatenation macros.  */
++
++#define CONCAT1(a, b) CONCAT2(a, b)
++#define CONCAT2(a, b) a ## b
++
++ /* Use the right prefix for global labels.  */
++
++#define SYM(x) CONCAT1 (__USER_LABEL_PREFIX__, x)
++
++#define FUNC(X)         .type SYM(X), at function
++#define ENDFUNC0(X)     .Lfe_##X: .size X,.Lfe_##X-X
++#define ENDFUNC(X)      ENDFUNC0(X)
++
++	.global SYM(__read_tp)
++SYM(__read_tp):
++	FUNC(__read_tp)
++	mov r0, CONCAT1 (r, __ARC_TLS_REGNO__)
++	nop
++	j [blink]
++	ENDFUNC(__read_tp)
++
++	.section .init
++	mov CONCAT1 (r, __ARC_TLS_REGNO__),__main_tcb_end+256
++
++	.section .tbss
++__main_tcb:
++	.long 0
++	.long 0
++__main_tcb_end:
++
++#endif /*__ARC_TLS_REGNO__ != -1 */
+diff --git a/libgcc/config/arc/t-arc b/libgcc/config/arc/t-arc
+index 7ceb694f69fd..3523aedec13b 100644
+--- a/libgcc/config/arc/t-arc
++++ b/libgcc/config/arc/t-arc
+@@ -68,6 +68,9 @@ crtg.o: $(srcdir)/config/arc/crtg.S
+ crtgend.o: $(srcdir)/config/arc/crtgend.S
+ 	$(crt_compile) -c -x assembler-with-cpp $<
+ 
++crttls.o: $(srcdir)/config/arc/crttls.S
++	$(crt_compile) -c -x assembler-with-cpp $<
++
+ mcount.o: $(srcdir)/config/arc/gmon/mcount.c
+ 	$(gcc_compile) -isystem $(srcdir)/config/arc/gmon -c $< \
+ 	-fcall-saved-r0 -fcall-saved-r1 -fcall-saved-r2 -fcall-saved-r3 \
+-- 
+2.7.4
+
diff --git a/toolchain/gcc/patches/6.3.0/0003-ARC-Add-TLS-support.patch b/toolchain/gcc/patches/6.3.0/0003-ARC-Add-TLS-support.patch
new file mode 100644
index 0000000..6eaf994
--- /dev/null
+++ b/toolchain/gcc/patches/6.3.0/0003-ARC-Add-TLS-support.patch
@@ -0,0 +1,1147 @@
+From e42098397e6646a8fa0a3c63e662c274a93bc464 Mon Sep 17 00:00:00 2001
+From: claziss <claziss at 138bc75d-0d04-0410-961f-82ee72b054a4>
+Date: Thu, 28 Apr 2016 11:53:46 +0000
+Subject: [PATCH 03/89] [ARC] Add TLS support.
+
+gcc/
+2016-04-28  Claudiu Zissulescu  <claziss at synopsys.com>
+	    Joern Rennecke  <joern.rennecke at embecosm.com>
+
+	* config/arc/arc-protos.h (arc_legitimize_pic_address): Remove
+	declaration.
+	(emit_pic_move): Remove.
+	(arc_eh_uses, insn_is_tls_gd_dispatch): Declare.
+	* config/arc/arc.c (emit_pic_move): Removed.
+	(TARGET_HAVE_TLS): Define.
+	(arc_conditional_register_usage): Test for arc_tp_regno.
+	(arc_print_operand, arc_print_operand_address): Handle TLS
+	unspecs.
+	(arc_needs_pcl_p): New function.
+	(arc_legitimate_pc_offset_p): Use arc_needs_pcl_p.
+	(arc_legitimate_pic_addr_p): Handle TLS unspecs.
+	(arc_raw_symbolic_reference_mentioned_p): Likewise.
+	(arc_get_tp, arc_emit_call_tls_get_addr): New function.
+	(arc_legitimize_tls_address): Likewise.
+	(DTPOFF_ZERO_SYM): Define.
+	(arc_legitimize_pic_address): Make it static, handle TLS cases.
+	(arc_output_pic_addr_const): Print TLS unspecs.
+	(prepare_pic_move): New function, replaces emit_pic_move.
+	(arc_legitimate_constant_p): Handle TLS unspecs.
+	(arc_legitimate_address_p): Likewise.
+	(arc_rewrite_small_data_p): Use assert for TLS constants.
+	(prepare_move_operands): Use prepare_pic_move.
+	(arc_legitimize_address): Legitimize tls addresses.
+	(arc_epilogue_uses): Check for arc_tp_regno.
+	(arc_eh_uses, insn_is_tls_gd_dispatch): New function.
+	* config/arc/arc.h [DEFAULT_LIBC != LIBC_UCLIBC] (EXTRA_SPECS):
+	Define.
+	[DEFAULT_LIBC != LIBC_UCLIBC] (ARC_TLS_EXTRA_START_SPEC):
+	Likewise.
+	[DEFAULT_LIBC != LIBC_UCLIBC] (STARTFILE_SPEC): Add
+	%(arc_tls_extra_start_spec).
+	(TARGET_CPU_CPP_BUILTINS): Define __ARC_TLS_REGNO__.
+	(REGNO_OK_FOR_BASE_P): Check for arc_tp_regno.
+	(EH_USES): Define.
+	(INSN_REFERENCES_ARE_DELAYED): Use insn_is_tls_gd_dispatch.
+	* config/arc/arc.md (UNSPEC_TLS_GD, UNSPEC_TLS_LD, UNSPEC_TLS_IE)
+	(UNSPEC_TLS_OFF): Add.
+	(R10_REG): Define.
+	(tls_load_tp_soft, tls_gd_load, tls_gd_get_addr, tls_gd_dispatch)
+	(get_thread_pointersi): New patterns.
+	* config/arc/arc.opt (mtp-regno): New option.
+	* config/arc/predicates.md (move_src_operand): Handle TLS symbols.
+	(move_dest_operand): Likewise.
+	* configure: Regenerate.
+	* configure.ac: Add arc*-*-* case to test for tls.
+	* doc/invoke.texi (ARC options): Document mtp-regno.
+
+git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@235559 138bc75d-0d04-0410-961f-82ee72b054a4
+---
+ gcc/ChangeLog                |  51 +++++
+ gcc/config/arc/arc-protos.h  |   4 +-
+ gcc/config/arc/arc.c         | 505 +++++++++++++++++++++++++++++++------------
+ gcc/config/arc/arc.h         |  22 +-
+ gcc/config/arc/arc.md        |  71 ++++++
+ gcc/config/arc/arc.opt       |   7 +
+ gcc/config/arc/predicates.md |  15 +-
+ gcc/configure                |   6 +
+ gcc/configure.ac             |   6 +
+ gcc/doc/invoke.texi          |   6 +-
+ 10 files changed, 545 insertions(+), 148 deletions(-)
+
+diff --git a/gcc/ChangeLog b/gcc/ChangeLog
+index a88e2f2ff8be..047bc20a9790 100644
+--- a/gcc/ChangeLog
++++ b/gcc/ChangeLog
+@@ -1,4 +1,55 @@
+ 2016-04-28  Claudiu Zissulescu  <claziss at synopsys.com>
++	    Joern Rennecke  <joern.rennecke at embecosm.com>
++
++	* config/arc/arc-protos.h (arc_legitimize_pic_address): Remove
++	declaration.
++	(emit_pic_move): Remove.
++	(arc_eh_uses, insn_is_tls_gd_dispatch): Declare.
++	* config/arc/arc.c (emit_pic_move): Removed.
++	(TARGET_HAVE_TLS): Define.
++	(arc_conditional_register_usage): Test for arc_tp_regno.
++	(arc_print_operand, arc_print_operand_address): Handle TLS
++	unspecs.
++	(arc_needs_pcl_p): New function.
++	(arc_legitimate_pc_offset_p): Use arc_needs_pcl_p.
++	(arc_legitimate_pic_addr_p): Handle TLS unspecs.
++	(arc_raw_symbolic_reference_mentioned_p): Likewise.
++	(arc_get_tp, arc_emit_call_tls_get_addr): New function.
++	(arc_legitimize_tls_address): Likewise.
++	(DTPOFF_ZERO_SYM): Define.
++	(arc_legitimize_pic_address): Make it static, handle TLS cases.
++	(arc_output_pic_addr_const): Print TLS unspecs.
++	(prepare_pic_move): New function, replaces emit_pic_move.
++	(arc_legitimate_constant_p): Handle TLS unspecs.
++	(arc_legitimate_address_p): Likewise.
++	(arc_rewrite_small_data_p): Use assert for TLS constants.
++	(prepare_move_operands): Use prepare_pic_move.
++	(arc_legitimize_address): Legitimize tls addresses.
++	(arc_epilogue_uses): Check for arc_tp_regno.
++	(arc_eh_uses, insn_is_tls_gd_dispatch): New function.
++	* config/arc/arc.h [DEFAULT_LIBC != LIBC_UCLIBC] (EXTRA_SPECS):
++	Define.
++	[DEFAULT_LIBC != LIBC_UCLIBC] (ARC_TLS_EXTRA_START_SPEC):
++	Likewise.
++	[DEFAULT_LIBC != LIBC_UCLIBC] (STARTFILE_SPEC): Add
++	%(arc_tls_extra_start_spec).
++	(TARGET_CPU_CPP_BUILTINS): Define __ARC_TLS_REGNO__.
++	(REGNO_OK_FOR_BASE_P): Check for arc_tp_regno.
++	(EH_USES): Define.
++	(INSN_REFERENCES_ARE_DELAYED): Use insn_is_tls_gd_dispatch.
++	* config/arc/arc.md (UNSPEC_TLS_GD, UNSPEC_TLS_LD, UNSPEC_TLS_IE)
++	(UNSPEC_TLS_OFF): Add.
++	(R10_REG): Define.
++	(tls_load_tp_soft, tls_gd_load, tls_gd_get_addr, tls_gd_dispatch)
++	(get_thread_pointersi): New patterns.
++	* config/arc/arc.opt (mtp-regno): New option.
++	* config/arc/predicates.md (move_src_operand): Handle TLS symbols.
++	(move_dest_operand): Likewise.
++	* configure: Regenerate.
++	* configure.ac: Add arc*-*-* case to test for tls.
++	* doc/invoke.texi (ARC options): Document mtp-regno.
++
++2016-04-28  Claudiu Zissulescu  <claziss at synopsys.com>
+ 
+ 	* config/arc/arc.c (arc_vector_mode_supported_p): Add support for
+ 	the new ARC HS SIMD instructions.
+diff --git a/gcc/config/arc/arc-protos.h b/gcc/config/arc/arc-protos.h
+index f487291d35d7..3bf28a088bd9 100644
+--- a/gcc/config/arc/arc-protos.h
++++ b/gcc/config/arc/arc-protos.h
+@@ -57,7 +57,6 @@ extern unsigned int arc_compute_frame_size (int);
+ extern bool arc_ccfsm_branch_deleted_p (void);
+ extern void arc_ccfsm_record_branch_deleted (void);
+ 
+-extern rtx arc_legitimize_pic_address (rtx, rtx);
+ void arc_asm_output_aligned_decl_local (FILE *, tree, const char *,
+ 					unsigned HOST_WIDE_INT,
+ 					unsigned HOST_WIDE_INT,
+@@ -68,7 +67,6 @@ extern bool check_if_valid_sleep_operand (rtx *, int);
+ extern bool arc_legitimate_constant_p (machine_mode, rtx);
+ extern bool arc_legitimate_pc_offset_p (rtx);
+ extern bool arc_legitimate_pic_addr_p (rtx);
+-extern void emit_pic_move (rtx *, machine_mode);
+ extern bool arc_raw_symbolic_reference_mentioned_p (rtx, bool);
+ extern bool arc_legitimate_pic_operand_p (rtx);
+ extern bool arc_is_longcall_p (rtx);
+@@ -118,8 +116,10 @@ extern bool arc_text_label (rtx_insn *insn);
+ extern int arc_decl_pretend_args (tree decl);
+ extern bool arc_short_comparison_p (rtx, int);
+ extern bool arc_epilogue_uses (int regno);
++extern bool arc_eh_uses (int regno);
+ /* insn-attrtab.c doesn't include reload.h, which declares regno_clobbered_p. */
+ extern int regno_clobbered_p (unsigned int, rtx_insn *, machine_mode, int);
+ extern int arc_return_slot_offset (void);
+ extern bool arc_legitimize_reload_address (rtx *, machine_mode, int, int);
+ extern void arc_secondary_reload_conv (rtx, rtx, rtx, bool);
++extern bool insn_is_tls_gd_dispatch (rtx_insn *);
+diff --git a/gcc/config/arc/arc.c b/gcc/config/arc/arc.c
+index d120946a5f2f..d40d54deb34a 100644
+--- a/gcc/config/arc/arc.c
++++ b/gcc/config/arc/arc.c
+@@ -217,7 +217,6 @@ static rtx arc_expand_builtin (tree, rtx, rtx, machine_mode, int);
+ static int branch_dest (rtx);
+ 
+ static void  arc_output_pic_addr_const (FILE *,  rtx, int);
+-void emit_pic_move (rtx *, machine_mode);
+ bool arc_legitimate_pic_operand_p (rtx);
+ static bool arc_function_ok_for_sibcall (tree, tree);
+ static rtx arc_function_value (const_tree, const_tree, bool);
+@@ -457,6 +456,11 @@ static void arc_finalize_pic (void);
+ #undef TARGET_ASM_ALIGNED_SI_OP
+ #define TARGET_ASM_ALIGNED_SI_OP "\t.word\t"
+ 
++#ifdef HAVE_AS_TLS
++#undef TARGET_HAVE_TLS
++#define TARGET_HAVE_TLS HAVE_AS_TLS
++#endif
++
+ #undef TARGET_DWARF_REGISTER_SPAN
+ #define TARGET_DWARF_REGISTER_SPAN arc_dwarf_register_span
+ 
+@@ -1322,6 +1326,14 @@ arc_conditional_register_usage (void)
+       strcpy (rname58, TARGET_BIG_ENDIAN ? "mhi" : "mlo");
+       strcpy (rname59, TARGET_BIG_ENDIAN ? "mlo" : "mhi");
+     }
++
++  /* The nature of arc_tp_regno is actually something more like a global
++     register, however globalize_reg requires a declaration.
++     We use EPILOGUE_USES to compensate so that sets from
++     __builtin_set_frame_pointer are not deleted.  */
++  if (arc_tp_regno != -1)
++    fixed_regs[arc_tp_regno] = call_used_regs[arc_tp_regno] = 1;
++
+   if (TARGET_MULMAC_32BY16_SET)
+     {
+       fix_start = 56;
+@@ -3411,7 +3423,16 @@ arc_print_operand (FILE *file, rtx x, int code)
+ 	}
+       /* Fall through.  Let output_addr_const deal with it.  */
+     default :
+-      if (flag_pic)
++      if (flag_pic
++	  || (GET_CODE (x) == CONST
++	      && GET_CODE (XEXP (x, 0)) == UNSPEC
++	      && (XINT (XEXP (x, 0), 1) == UNSPEC_TLS_OFF
++		  || XINT (XEXP (x, 0), 1) == UNSPEC_TLS_GD))
++	  || (GET_CODE (x) == CONST
++	      && GET_CODE (XEXP (x, 0)) == PLUS
++	      && GET_CODE (XEXP (XEXP (x, 0), 0)) == UNSPEC
++	      && (XINT (XEXP (XEXP (x, 0), 0), 1) == UNSPEC_TLS_OFF
++		  || XINT (XEXP (XEXP (x, 0), 0), 1) == UNSPEC_TLS_GD)))
+ 	arc_output_pic_addr_const (file, x, code);
+       else
+ 	{
+@@ -3476,6 +3497,17 @@ arc_print_operand_address (FILE *file , rtx addr)
+       {
+ 	rtx c = XEXP (addr, 0);
+ 
++	if ((GET_CODE (c) == UNSPEC
++	     && (XINT (c, 1) == UNSPEC_TLS_OFF
++		 || XINT (c, 1) == UNSPEC_TLS_IE))
++	    || (GET_CODE (c) == PLUS
++		&& GET_CODE (XEXP (c, 0)) == UNSPEC
++		&& (XINT (XEXP (c, 0), 1) == UNSPEC_TLS_OFF)))
++	  {
++	    arc_output_pic_addr_const (file, c, 0);
++	    break;
++	  }
++	gcc_assert (GET_CODE (c) == PLUS);
+ 	gcc_assert (GET_CODE (XEXP (c, 0)) == SYMBOL_REF);
+ 	gcc_assert (GET_CODE (XEXP (c, 1)) == CONST_INT);
+ 
+@@ -4547,6 +4579,44 @@ arc_rtx_costs (rtx x, machine_mode mode, int outer_code,
+     }
+ }
+ 
++/* Helper used by arc_legitimate_pc_offset_p.  */
++
++static bool
++arc_needs_pcl_p (rtx x)
++{
++  register const char *fmt;
++  register int i, j;
++
++  if ((GET_CODE (x) == UNSPEC)
++      && (XVECLEN (x, 0) == 1)
++      && (GET_CODE (XVECEXP (x, 0, 0)) == SYMBOL_REF))
++    switch (XINT (x, 1))
++      {
++      case ARC_UNSPEC_GOT:
++      case UNSPEC_TLS_GD:
++      case UNSPEC_TLS_IE:
++	return true;
++      default:
++	break;
++      }
++
++  fmt = GET_RTX_FORMAT (GET_CODE (x));
++  for (i = GET_RTX_LENGTH (GET_CODE (x)) - 1; i >= 0; i--)
++    {
++      if (fmt[i] == 'e')
++	{
++	  if (arc_needs_pcl_p (XEXP (x, i)))
++	    return true;
++	}
++      else if (fmt[i] == 'E')
++	for (j = XVECLEN (x, i) - 1; j >= 0; j--)
++	  if (arc_needs_pcl_p (XVECEXP (x, i, j)))
++	    return true;
++    }
++
++  return false;
++}
++
+ /* Return true if ADDR is an address that needs to be expressed as an
+    explicit sum of pcl + offset.  */
+ 
+@@ -4555,17 +4625,8 @@ arc_legitimate_pc_offset_p (rtx addr)
+ {
+   if (GET_CODE (addr) != CONST)
+     return false;
+-  addr = XEXP (addr, 0);
+-  if (GET_CODE (addr) == PLUS)
+-    {
+-      if (GET_CODE (XEXP (addr, 1)) != CONST_INT)
+-	return false;
+-      addr = XEXP (addr, 0);
+-    }
+-  return (GET_CODE (addr) == UNSPEC
+-	  && XVECLEN (addr, 0) == 1
+-	  && XINT (addr, 1) == ARC_UNSPEC_GOT
+-	  && GET_CODE (XVECEXP (addr, 0, 0)) == SYMBOL_REF);
++
++  return arc_needs_pcl_p (addr);
+ }
+ 
+ /* Return true if ADDR is a valid pic address.
+@@ -4594,9 +4655,11 @@ arc_legitimate_pic_addr_p (rtx addr)
+       || XVECLEN (addr, 0) != 1)
+     return false;
+ 
+-  /* Must be @GOT or @GOTOFF.  */
++  /* Must be one of @GOT, @GOTOFF, @tlsgd, tlsie.  */
+   if (XINT (addr, 1) != ARC_UNSPEC_GOT
+-      && XINT (addr, 1) != ARC_UNSPEC_GOTOFF)
++      && XINT (addr, 1) != ARC_UNSPEC_GOTOFF
++      && XINT (addr, 1) != UNSPEC_TLS_GD
++      && XINT (addr, 1) != UNSPEC_TLS_IE)
+     return false;
+ 
+   if (GET_CODE (XVECEXP (addr, 0, 0)) != SYMBOL_REF
+@@ -4654,6 +4717,10 @@ arc_raw_symbolic_reference_mentioned_p (rtx op, bool skip_local)
+ 
+   if (GET_CODE (op) == SYMBOL_REF)
+     {
++      if (SYMBOL_REF_TLS_MODEL (op))
++	return true;
++      if (!flag_pic)
++	return false;
+       tree decl = SYMBOL_REF_DECL (op);
+       return !skip_local || !decl || !default_binds_local_p (decl);
+     }
+@@ -4680,11 +4747,114 @@ arc_raw_symbolic_reference_mentioned_p (rtx op, bool skip_local)
+   return false;
+ }
+ 
++/* Get the thread pointer.  */
++
++static rtx
++arc_get_tp (void)
++{
++   /* If arc_tp_regno has been set, we can use that hard register
++      directly as a base register.  */
++  if (arc_tp_regno != -1)
++    return gen_rtx_REG (Pmode, arc_tp_regno);
++
++  /* Otherwise, call __read_tp.  Copy the result to a pseudo to avoid
++     conflicts with function arguments / results.  */
++  rtx reg = gen_reg_rtx (Pmode);
++  emit_insn (gen_tls_load_tp_soft ());
++  emit_move_insn (reg, gen_rtx_REG (Pmode, R0_REG));
++  return reg;
++}
++
++/* Helper to be used by TLS Global dynamic model.  */
++
++static rtx
++arc_emit_call_tls_get_addr (rtx sym, int reloc, rtx eqv)
++{
++  rtx r0 = gen_rtx_REG (Pmode, R0_REG);
++  rtx insns;
++  rtx call_fusage = NULL_RTX;
++
++  start_sequence ();
++
++  rtx x = gen_rtx_UNSPEC (Pmode, gen_rtvec (1, sym), reloc);
++  x = gen_rtx_CONST (Pmode, x);
++  emit_move_insn (r0, x);
++  use_reg (&call_fusage, r0);
++
++  gcc_assert (reloc == UNSPEC_TLS_GD);
++  rtx call_insn = emit_call_insn (gen_tls_gd_get_addr (sym));
++  /* Should we set RTL_CONST_CALL_P?  We read memory, but not in a
++     way that the application should care.  */
++  RTL_PURE_CALL_P (call_insn) = 1;
++  add_function_usage_to (call_insn, call_fusage);
++
++  insns = get_insns ();
++  end_sequence ();
++
++  rtx dest = gen_reg_rtx (Pmode);
++  emit_libcall_block (insns, dest, r0, eqv);
++  return dest;
++}
++
++#define DTPOFF_ZERO_SYM ".tdata"
++
++/* Return a legitimized address for ADDR,
++   which is a SYMBOL_REF with tls_model MODEL.  */
++
++static rtx
++arc_legitimize_tls_address (rtx addr, enum tls_model model)
++{
++  if (!flag_pic && model == TLS_MODEL_LOCAL_DYNAMIC)
++    model = TLS_MODEL_LOCAL_EXEC;
++
++  switch (model)
++    {
++    case TLS_MODEL_LOCAL_DYNAMIC:
++      rtx base;
++      tree decl;
++      const char *base_name;
++      rtvec v;
++
++      decl = SYMBOL_REF_DECL (addr);
++      base_name = DTPOFF_ZERO_SYM;
++      if (decl && bss_initializer_p (decl))
++	base_name = ".tbss";
++
++      base = gen_rtx_SYMBOL_REF (Pmode, base_name);
++      if (strcmp (base_name, DTPOFF_ZERO_SYM) == 0)
++	{
++	  if (!flag_pic)
++	    goto local_exec;
++	  v = gen_rtvec (1, addr);
++	}
++      else
++	v = gen_rtvec (2, addr, base);
++      addr = gen_rtx_UNSPEC (Pmode, v, UNSPEC_TLS_OFF);
++      addr = gen_rtx_CONST (Pmode, addr);
++      base = arc_legitimize_tls_address (base, TLS_MODEL_GLOBAL_DYNAMIC);
++      return gen_rtx_PLUS (Pmode, force_reg (Pmode, base), addr);
++    case TLS_MODEL_GLOBAL_DYNAMIC:
++      return arc_emit_call_tls_get_addr (addr, UNSPEC_TLS_GD, addr);
++    case TLS_MODEL_INITIAL_EXEC:
++      addr = gen_rtx_UNSPEC (Pmode, gen_rtvec (1, addr), UNSPEC_TLS_IE);
++      addr = gen_rtx_CONST (Pmode, addr);
++      addr = copy_to_mode_reg (Pmode, gen_const_mem (Pmode, addr));
++      return gen_rtx_PLUS (Pmode, arc_get_tp (), addr);
++    case TLS_MODEL_LOCAL_EXEC:
++    local_exec:
++      addr = gen_rtx_UNSPEC (Pmode, gen_rtvec (1, addr), UNSPEC_TLS_OFF);
++      addr = gen_rtx_CONST (Pmode, addr);
++      return gen_rtx_PLUS (Pmode, arc_get_tp (), addr);
++    default:
++      gcc_unreachable ();
++    }
++}
++
+ /* Legitimize a pic address reference in ORIG.
+    The return value is the legitimated address.
+    If OLDX is non-zero, it is the target to assign the address to first.  */
+ 
+-rtx
++static rtx
+ arc_legitimize_pic_address (rtx orig, rtx oldx)
+ {
+   rtx addr = orig;
+@@ -4696,40 +4866,36 @@ arc_legitimize_pic_address (rtx orig, rtx oldx)
+ 
+   if (GET_CODE (addr) == LABEL_REF)
+     ; /* Do nothing.  */
+-  else if (GET_CODE (addr) == SYMBOL_REF
+-	   && (CONSTANT_POOL_ADDRESS_P (addr)
+-	       || SYMBOL_REF_LOCAL_P (addr)))
++  else if (GET_CODE (addr) == SYMBOL_REF)
+     {
+-      /* This symbol may be referenced via a displacement from the PIC
+-	 base address (@GOTOFF).  */
+-
+-      /* FIXME: if we had a way to emit pc-relative adds that don't
+-	 create a GOT entry, we could do without the use of the gp register.  */
+-      crtl->uses_pic_offset_table = 1;
+-      pat = gen_rtx_UNSPEC (Pmode, gen_rtvec (1, addr), ARC_UNSPEC_GOTOFF);
+-      pat = gen_rtx_CONST (Pmode, pat);
+-      pat = gen_rtx_PLUS (Pmode, pic_offset_table_rtx, pat);
+-
+-      if (oldx == NULL)
+-	oldx = gen_reg_rtx (Pmode);
+-
+-      if (oldx != 0)
++      enum tls_model model = SYMBOL_REF_TLS_MODEL (addr);
++      if (model != 0)
++	return arc_legitimize_tls_address (addr, model);
++      else if (!flag_pic)
++	return orig;
++      else if (CONSTANT_POOL_ADDRESS_P (addr) || SYMBOL_REF_LOCAL_P (addr))
+ 	{
+-	  emit_move_insn (oldx, pat);
+-	  pat = oldx;
++	  /* This symbol may be referenced via a displacement from the
++	     PIC base address (@GOTOFF).  */
++
++	  /* FIXME: if we had a way to emit pc-relative adds that
++	     don't create a GOT entry, we could do without the use of
++	     the gp register.  */
++	  crtl->uses_pic_offset_table = 1;
++	  pat = gen_rtx_UNSPEC (Pmode, gen_rtvec (1, addr), ARC_UNSPEC_GOTOFF);
++	  pat = gen_rtx_CONST (Pmode, pat);
++	  pat = gen_rtx_PLUS (Pmode, pic_offset_table_rtx, pat);
++	}
++      else
++	{
++	  /* This symbol must be referenced via a load from the
++	     Global Offset Table (@GOTPC).  */
++	  pat = gen_rtx_UNSPEC (Pmode, gen_rtvec (1, addr), ARC_UNSPEC_GOT);
++	  pat = gen_rtx_CONST (Pmode, pat);
++	  pat = gen_const_mem (Pmode, pat);
+ 	}
+ 
+-    }
+-  else if (GET_CODE (addr) == SYMBOL_REF)
+-    {
+-      /* This symbol must be referenced via a load from the
+-	 Global Offset Table (@GOTPC).  */
+-
+-      pat = gen_rtx_UNSPEC (Pmode, gen_rtvec (1, addr), ARC_UNSPEC_GOT);
+-      pat = gen_rtx_CONST (Pmode, pat);
+-      pat = gen_const_mem (Pmode, pat);
+-
+-      if (oldx == 0)
++      if (oldx == NULL)
+ 	oldx = gen_reg_rtx (Pmode);
+ 
+       emit_move_insn (oldx, pat);
+@@ -4752,45 +4918,23 @@ arc_legitimize_pic_address (rtx orig, rtx oldx)
+ 	{
+ 	  rtx op0 = XEXP (addr, 0), op1 = XEXP (addr, 1);
+ 
+-	  /* Check first to see if this is a constant offset from a @GOTOFF
+-	     symbol reference.  */
+-	  if ((GET_CODE (op0) == LABEL_REF
+-	       || (GET_CODE (op0) == SYMBOL_REF
+-		   && (CONSTANT_POOL_ADDRESS_P (op0)
+-		       || SYMBOL_REF_LOCAL_P (op0))))
+-	      && GET_CODE (op1) == CONST_INT)
+-	    {
+-	      /* FIXME: like above, could do without gp reference.  */
+-	      crtl->uses_pic_offset_table = 1;
+-	      pat
+-		= gen_rtx_UNSPEC (Pmode, gen_rtvec (1, op0), ARC_UNSPEC_GOTOFF);
+-	      pat = gen_rtx_PLUS (Pmode, pat, op1);
+-	      pat = gen_rtx_CONST (Pmode, pat);
+-	      pat = gen_rtx_PLUS (Pmode, pic_offset_table_rtx, pat);
+-
+-	      if (oldx != 0)
+-		{
+-		  emit_move_insn (oldx, pat);
+-		  pat = oldx;
+-		}
+-	    }
+-	  else
+-	    {
+-	      base = arc_legitimize_pic_address (XEXP (addr, 0), oldx);
+-	      pat  = arc_legitimize_pic_address (XEXP (addr, 1),
++	  base = arc_legitimize_pic_address (op0, oldx);
++	  pat  = arc_legitimize_pic_address (op1,
+ 					     base == oldx ? NULL_RTX : oldx);
+ 
+-	      if (GET_CODE (pat) == CONST_INT)
+-		pat = plus_constant (Pmode, base, INTVAL (pat));
+-	      else
++	  if (base == op0 && pat == op1)
++	    return orig;
++
++	  if (GET_CODE (pat) == CONST_INT)
++	    pat = plus_constant (Pmode, base, INTVAL (pat));
++	  else
++	    {
++	      if (GET_CODE (pat) == PLUS && CONSTANT_P (XEXP (pat, 1)))
+ 		{
+-		  if (GET_CODE (pat) == PLUS && CONSTANT_P (XEXP (pat, 1)))
+-		    {
+-		      base = gen_rtx_PLUS (Pmode, base, XEXP (pat, 0));
+-		      pat = XEXP (pat, 1);
+-		    }
+-		  pat = gen_rtx_PLUS (Pmode, base, pat);
++		  base = gen_rtx_PLUS (Pmode, base, XEXP (pat, 0));
++		  pat = XEXP (pat, 1);
+ 		}
++	      pat = gen_rtx_PLUS (Pmode, base, pat);
+ 	    }
+ 	}
+     }
+@@ -4906,26 +5050,47 @@ arc_output_pic_addr_const (FILE * file, rtx x, int code)
+ 
+ 
+     case UNSPEC:
+-      gcc_assert (XVECLEN (x, 0) == 1);
+-      if (XINT (x, 1) == ARC_UNSPEC_GOT)
+-	fputs ("pcl,", file);
+-      arc_output_pic_addr_const (file, XVECEXP (x, 0, 0), code);
++      const char *suffix;
++      bool pcrel; pcrel = false;
++      rtx base; base = NULL;
++      gcc_assert (XVECLEN (x, 0) >= 1);
+       switch (XINT (x, 1))
+ 	{
+ 	case ARC_UNSPEC_GOT:
+-	  fputs ("@gotpc", file);
++	  suffix = "@gotpc", pcrel = true;
+ 	  break;
+ 	case ARC_UNSPEC_GOTOFF:
+-	  fputs ("@gotoff", file);
++	  suffix = "@gotoff";
+ 	  break;
+ 	case ARC_UNSPEC_PLT:
+-	  fputs ("@plt", file);
++	  suffix = "@plt";
++	  break;
++	case UNSPEC_TLS_GD:
++	  suffix = "@tlsgd", pcrel = true;
++	  break;
++	case UNSPEC_TLS_IE:
++	  suffix = "@tlsie", pcrel = true;
++	  break;
++	case UNSPEC_TLS_OFF:
++	  if (XVECLEN (x, 0) == 2)
++	    base = XVECEXP (x, 0, 1);
++	  if (SYMBOL_REF_TLS_MODEL (XVECEXP (x, 0, 0)) == TLS_MODEL_LOCAL_EXEC
++	      || (!flag_pic && !base))
++	    suffix = "@tpoff";
++	  else
++	    suffix = "@dtpoff";
+ 	  break;
+ 	default:
+ 	  output_operand_lossage ("invalid UNSPEC as operand: %d", XINT (x,1));
+ 	  break;
+ 	}
+-       break;
++      if (pcrel)
++	fputs ("pcl,", file);
++      arc_output_pic_addr_const (file, XVECEXP (x, 0, 0), code);
++      fputs (suffix, file);
++      if (base)
++	arc_output_pic_addr_const (file, base, code);
++      break;
+ 
+     default:
+       output_operand_lossage ("invalid expression as operand");
+@@ -4939,15 +5104,18 @@ arc_output_pic_addr_const (FILE * file, rtx x, int code)
+ 
+ /* Emit insns to move operands[1] into operands[0].  */
+ 
+-void
+-emit_pic_move (rtx *operands, machine_mode)
++static void
++prepare_pic_move (rtx *operands, machine_mode)
+ {
+-  rtx temp = reload_in_progress ? operands[0] : gen_reg_rtx (Pmode);
+-
+-  if (GET_CODE (operands[0]) == MEM && SYMBOLIC_CONST (operands[1]))
++  if (GET_CODE (operands[0]) == MEM && SYMBOLIC_CONST (operands[1])
++      && flag_pic)
+     operands[1] = force_reg (Pmode, operands[1]);
+   else
+-    operands[1] = arc_legitimize_pic_address (operands[1], temp);
++    {
++      rtx temp = (reload_in_progress ? operands[0]
++		  : flag_pic? gen_reg_rtx (Pmode) : NULL_RTX);
++      operands[1] = arc_legitimize_pic_address (operands[1], temp);
++    }
+ }
+ 
+ 
+@@ -5149,9 +5317,12 @@ arc_legitimate_pic_operand_p (rtx x)
+    satisfies CONSTANT_P.  */
+ 
+ bool
+-arc_legitimate_constant_p (machine_mode, rtx x)
++arc_legitimate_constant_p (machine_mode mode, rtx x)
+ {
+-  if (!flag_pic)
++  if (GET_CODE (x) == SYMBOL_REF && SYMBOL_REF_TLS_MODEL (x))
++    return false;
++
++  if (!flag_pic && mode != Pmode)
+     return true;
+ 
+   switch (GET_CODE (x))
+@@ -5161,7 +5332,9 @@ arc_legitimate_constant_p (machine_mode, rtx x)
+ 
+       if (GET_CODE (x) == PLUS)
+ 	{
+-	  if (GET_CODE (XEXP (x, 1)) != CONST_INT)
++	  if (flag_pic
++	      ? GET_CODE (XEXP (x, 1)) != CONST_INT
++	      : !arc_legitimate_constant_p (mode, XEXP (x, 1)))
+ 	    return false;
+ 	  x = XEXP (x, 0);
+ 	}
+@@ -5173,6 +5346,9 @@ arc_legitimate_constant_p (machine_mode, rtx x)
+ 	  case ARC_UNSPEC_PLT:
+ 	  case ARC_UNSPEC_GOTOFF:
+ 	  case ARC_UNSPEC_GOT:
++	  case UNSPEC_TLS_GD:
++	  case UNSPEC_TLS_IE:
++	  case UNSPEC_TLS_OFF:
+ 	  case UNSPEC_PROF:
+ 	    return true;
+ 
+@@ -5187,9 +5363,14 @@ arc_legitimate_constant_p (machine_mode, rtx x)
+       /* Return true.  */
+       break;
+ 
+-    case LABEL_REF:
+     case SYMBOL_REF:
+-      return false;
++      if (SYMBOL_REF_TLS_MODEL (x))
++	return false;
++      /* Fall through.  */
++    case LABEL_REF:
++      if (flag_pic)
++	return false;
++      /* Fall through.  */
+ 
+     default:
+       break;
+@@ -5212,12 +5393,29 @@ arc_legitimate_address_p (machine_mode mode, rtx x, bool strict)
+      return true;
+   if (GET_CODE (x) == CONST_INT && LARGE_INT (INTVAL (x)))
+      return true;
+-  if ((GET_MODE_SIZE (mode) != 16)
+-      && (GET_CODE (x) == SYMBOL_REF
+-	  || GET_CODE (x) == LABEL_REF
+-	  || GET_CODE (x) == CONST))
++
++  /* When we compile for size avoid const (@sym + offset)
++     addresses.  */
++  if (!flag_pic && optimize_size && !reload_completed
++      && (GET_CODE (x) == CONST)
++      && (GET_CODE (XEXP (x, 0)) == PLUS)
++      && (GET_CODE (XEXP (XEXP (x, 0), 0)) == SYMBOL_REF)
++      && SYMBOL_REF_TLS_MODEL (XEXP (XEXP (x, 0), 0)) == 0
++      && !SYMBOL_REF_FUNCTION_P (XEXP (XEXP (x, 0), 0)))
+     {
+-      if (!flag_pic || arc_legitimate_pic_addr_p (x))
++      rtx addend = XEXP (XEXP (x, 0), 1);
++      gcc_assert (CONST_INT_P (addend));
++      HOST_WIDE_INT offset = INTVAL (addend);
++
++      /* Allow addresses having a large offset to pass.  Anyhow they
++	 will end in a limm.  */
++      return !(offset > -1024 && offset < 1020);
++    }
++
++  if ((GET_MODE_SIZE (mode) != 16) && CONSTANT_P (x))
++    {
++      if (flag_pic ? arc_legitimate_pic_addr_p (x)
++	  : arc_legitimate_constant_p (Pmode, x))
+ 	return true;
+     }
+   if ((GET_CODE (x) == PRE_DEC || GET_CODE (x) == PRE_INC
+@@ -6860,8 +7058,12 @@ arc_rewrite_small_data_p (const_rtx x)
+ 	x = XEXP (x, 0);
+     }
+ 
+-  return (GET_CODE (x) ==  SYMBOL_REF
+-	  && SYMBOL_REF_SMALL_P(x));
++  if (GET_CODE (x) == SYMBOL_REF && SYMBOL_REF_SMALL_P (x))
++    {
++      gcc_assert (SYMBOL_REF_TLS_MODEL (x) == 0);
++      return true;
++    }
++  return false;
+ }
+ 
+ /* If possible, rewrite OP so that it refers to small data using
+@@ -7280,40 +7482,39 @@ prepare_move_operands (rtx *operands, machine_mode mode)
+ {
+   /* We used to do this only for MODE_INT Modes, but addresses to floating
+      point variables may well be in the small data section.  */
+-  if (1)
++  if (!TARGET_NO_SDATA_SET && small_data_pattern (operands[0], Pmode))
++    operands[0] = arc_rewrite_small_data (operands[0]);
++
++  if (mode == SImode && SYMBOLIC_CONST (operands[1]))
+     {
+-      if (!TARGET_NO_SDATA_SET && small_data_pattern (operands[0], Pmode))
+-	operands[0] = arc_rewrite_small_data (operands[0]);
+-      else if (mode == SImode && flag_pic && SYMBOLIC_CONST (operands[1]))
+-	{
+-	  emit_pic_move (operands, SImode);
++      prepare_pic_move (operands, SImode);
+ 
+-	  /* Disable any REG_EQUALs associated with the symref
+-	     otherwise the optimization pass undoes the work done
+-	     here and references the variable directly.  */
+-	}
+-      else if (GET_CODE (operands[0]) != MEM
+-	       && !TARGET_NO_SDATA_SET
+-	       && small_data_pattern (operands[1], Pmode))
+-       {
+-	  /* This is to take care of address calculations involving sdata
+-	     variables.  */
+-	  operands[1] = arc_rewrite_small_data (operands[1]);
+-
+-	  emit_insn (gen_rtx_SET (operands[0],operands[1]));
+-	  /* ??? This note is useless, since it only restates the set itself.
+-	     We should rather use the original SYMBOL_REF.  However, there is
+-	     the problem that we are lying to the compiler about these
+-	     SYMBOL_REFs to start with.  symbol at sda should be encoded specially
+-	     so that we can tell it apart from an actual symbol.  */
+-	  set_unique_reg_note (get_last_insn (), REG_EQUAL, operands[1]);
+-
+-	  /* Take care of the REG_EQUAL note that will be attached to mark the
+-	     output reg equal to the initial symbol_ref after this code is
+-	     executed.  */
+-	  emit_move_insn (operands[0], operands[0]);
+-	  return true;
+-	}
++      /* Disable any REG_EQUALs associated with the symref
++	 otherwise the optimization pass undoes the work done
++	 here and references the variable directly.  */
++    }
++
++  if (GET_CODE (operands[0]) != MEM
++      && !TARGET_NO_SDATA_SET
++      && small_data_pattern (operands[1], Pmode))
++    {
++      /* This is to take care of address calculations involving sdata
++	 variables.  */
++      operands[1] = arc_rewrite_small_data (operands[1]);
++
++      emit_insn (gen_rtx_SET (operands[0],operands[1]));
++      /* ??? This note is useless, since it only restates the set itself.
++	 We should rather use the original SYMBOL_REF.  However, there is
++	 the problem that we are lying to the compiler about these
++	 SYMBOL_REFs to start with.  symbol at sda should be encoded specially
++	 so that we can tell it apart from an actual symbol.  */
++      set_unique_reg_note (get_last_insn (), REG_EQUAL, operands[1]);
++
++      /* Take care of the REG_EQUAL note that will be attached to mark the
++	 output reg equal to the initial symbol_ref after this code is
++	 executed.  */
++      emit_move_insn (operands[0], operands[0]);
++      return true;
+     }
+ 
+   if (MEM_P (operands[0])
+@@ -8311,6 +8512,13 @@ arc_legitimize_address_0 (rtx x, rtx oldx ATTRIBUTE_UNUSED,
+ static rtx
+ arc_legitimize_address (rtx orig_x, rtx oldx, machine_mode mode)
+ {
++  if (GET_CODE (orig_x) == SYMBOL_REF)
++    {
++      enum tls_model model = SYMBOL_REF_TLS_MODEL (orig_x);
++      if (model != 0)
++	return arc_legitimize_tls_address (orig_x, model);
++    }
++
+   rtx new_x = arc_legitimize_address_0 (orig_x, oldx, mode);
+ 
+   if (new_x)
+@@ -9070,6 +9278,8 @@ arc_can_follow_jump (const rtx_insn *follower, const rtx_insn *followee)
+ bool
+ arc_epilogue_uses (int regno)
+ {
++  if (regno == arc_tp_regno)
++    return true;
+   if (reload_completed)
+     {
+       if (ARC_INTERRUPT_P (cfun->machine->fn_type))
+@@ -9085,6 +9295,16 @@ arc_epilogue_uses (int regno)
+     return regno == arc_return_address_regs[arc_compute_function_type (cfun)];
+ }
+ 
++/* Helper for EH_USES macro.  */
++
++bool
++arc_eh_uses (int regno)
++{
++  if (regno == arc_tp_regno)
++    return true;
++  return false;
++}
++
+ #ifndef TARGET_NO_LRA
+ #define TARGET_NO_LRA !TARGET_LRA
+ #endif
+@@ -9590,6 +9810,13 @@ arc_dwarf_register_span (rtx rtl)
+    return p;
+ }
+ 
++/* We can't inline this in INSN_REFERENCES_ARE_DELAYED because
++   resource.h doesn't include the required header files.  */
++bool
++insn_is_tls_gd_dispatch (rtx_insn *insn)
++{
++  return recog_memoized (insn) == CODE_FOR_tls_gd_dispatch;
++}
+ 
+ struct gcc_target targetm = TARGET_INITIALIZER;
+ 
+diff --git a/gcc/config/arc/arc.h b/gcc/config/arc/arc.h
+index 5100a5b8f821..de6c6d11974a 100644
+--- a/gcc/config/arc/arc.h
++++ b/gcc/config/arc/arc.h
+@@ -109,6 +109,8 @@ along with GCC; see the file COPYING3.  If not see
+       builtin_define ("__ARC_SIMD__");	\
+     if (TARGET_BARREL_SHIFTER)		\
+       builtin_define ("__Xbarrel_shifter");\
++    builtin_define_with_int_value ("__ARC_TLS_REGNO__", \
++				   arc_tp_regno);	\
+     builtin_assert ("cpu=arc");		\
+     builtin_assert ("machine=arc");	\
+     builtin_define (TARGET_BIG_ENDIAN	\
+@@ -201,7 +203,13 @@ along with GCC; see the file COPYING3.  If not see
+ #endif
+ 
+ #if DEFAULT_LIBC != LIBC_UCLIBC
+-#define STARTFILE_SPEC "%{!shared:crt0.o%s} crti%O%s %{pg|p:crtg.o%s} crtbegin.o%s"
++#define ARC_TLS_EXTRA_START_SPEC "crttls.o%s"
++
++#define EXTRA_SPECS \
++  { "arc_tls_extra_start_spec", ARC_TLS_EXTRA_START_SPEC }, \
++
++#define STARTFILE_SPEC "%{!shared:crt0.o%s} crti%O%s %{pg|p:crtg.o%s} " \
++  "%(arc_tls_extra_start_spec) crtbegin.o%s"
+ #else
+ #define STARTFILE_SPEC   "%{!shared:%{!mkernel:crt1.o%s}} crti.o%s \
+   %{!shared:%{pg|p|profile:crtg.o%s} crtbegin.o%s} %{shared:crtbeginS.o%s}"
+@@ -748,9 +756,10 @@ extern enum reg_class arc_regno_reg_class[];
+    or a pseudo reg currently allocated to a suitable hard reg.
+    Since they use reg_renumber, they are safe only once reg_renumber
+    has been allocated, which happens in local-alloc.c.  */
+-#define REGNO_OK_FOR_BASE_P(REGNO) \
+-((REGNO) < 29 || ((REGNO) == ARG_POINTER_REGNUM) || ((REGNO) == 63) ||\
+- (unsigned) reg_renumber[REGNO] < 29)
++#define REGNO_OK_FOR_BASE_P(REGNO)					\
++  ((REGNO) < 29 || ((REGNO) == ARG_POINTER_REGNUM) || ((REGNO) == 63)	\
++   || ((unsigned) reg_renumber[REGNO] < 29)				\
++   || ((unsigned) (REGNO) == (unsigned) arc_tp_regno))
+ 
+ #define REGNO_OK_FOR_INDEX_P(REGNO) REGNO_OK_FOR_BASE_P(REGNO)
+ 
+@@ -937,6 +946,8 @@ arc_return_addr_rtx(COUNT,FRAME)
+ 
+ #define EPILOGUE_USES(REGNO) arc_epilogue_uses ((REGNO))
+ 
++#define EH_USES(REGNO) arc_eh_uses((REGNO))
++
+ /* Definitions for register eliminations.
+ 
+    This is an array of structures.  Each structure initializes one pair
+@@ -1657,7 +1668,8 @@ extern enum arc_function_type arc_compute_function_type (struct function *);
+    && GET_CODE (PATTERN (X)) != CLOBBER		\
+    && (get_attr_type (X) == TYPE_CALL || get_attr_type (X) == TYPE_SFUNC))
+ 
+-#define INSN_REFERENCES_ARE_DELAYED(insn) INSN_SETS_ARE_DELAYED (insn)
++#define INSN_REFERENCES_ARE_DELAYED(insn)				\
++  (INSN_SETS_ARE_DELAYED (insn) && !insn_is_tls_gd_dispatch (insn))
+ 
+ #define CALL_ATTR(X, NAME) \
+   ((CALL_P (X) || NONJUMP_INSN_P (X)) \
+diff --git a/gcc/config/arc/arc.md b/gcc/config/arc/arc.md
+index 4193d2610f19..4a7287b05365 100644
+--- a/gcc/config/arc/arc.md
++++ b/gcc/config/arc/arc.md
+@@ -111,6 +111,10 @@
+   ARC_UNSPEC_PLT
+   ARC_UNSPEC_GOT
+   ARC_UNSPEC_GOTOFF
++  UNSPEC_TLS_GD
++  UNSPEC_TLS_LD
++  UNSPEC_TLS_IE
++  UNSPEC_TLS_OFF
+   UNSPEC_ARC_NORM
+   UNSPEC_ARC_NORMW
+   UNSPEC_ARC_SWAP
+@@ -169,6 +173,7 @@
+    (R1_REG 1)
+    (R2_REG 2)
+    (R3_REG 3)
++   (R10_REG 10)
+    (R12_REG 12)
+    (SP_REG 28)
+    (ILINK1_REGNUM 29)
+@@ -5277,6 +5282,72 @@
+   [(set_attr "type" "call")
+    (set_attr "is_SIBCALL" "yes")])
+ 
++(define_insn "tls_load_tp_soft"
++  [(set (reg:SI R0_REG) (unspec:SI [(const_int 0)] UNSPEC_TLS_OFF))
++   (clobber (reg:SI RETURN_ADDR_REGNUM))]
++  ""
++  "*return arc_output_libcall (\"__read_tp\");"
++  [(set_attr "is_sfunc" "yes")
++   (set_attr "predicable" "yes")])
++
++(define_insn "tls_gd_load"
++  [(set (match_operand:SI 0 "dest_reg_operand" "=Rcq#q,c")
++	(unspec:SI [(match_operand:SI 1 "register_operand" "Rcq#q,c")
++		    (match_operand:SI 2 "symbolic_operand" "X,X")]
++	 UNSPEC_TLS_GD))]
++  ""
++  ".tls_gd_ld %2`ld%? %0,[%1]"
++  [(set_attr "type" "load")
++   ; if the linker has to patch this into IE, we need a long insn
++   ; (FIXME: or two short insn, ld_s / jl_s.  missing -Os optimization.)
++   (set_attr_alternative "iscompact"
++     [(cond [(ne (symbol_ref "arc_tp_regno == 30") (const_int 0))
++	     (const_string "*")] (const_string "maybe"))
++      (const_string "*")])])
++
++(define_insn "tls_gd_get_addr"
++  [(set (reg:SI R0_REG)
++	(call:SI (mem:SI (unspec:SI [(match_operand:SI 0
++				      "symbolic_operand" "X,X")]
++			  UNSPEC_TLS_GD))
++		 (const_int 0)))
++   (clobber (reg:SI RETURN_ADDR_REGNUM))]
++  ""
++  ".tls_gd_ld %0`bl%* __tls_get_addr at plt"
++  [(set_attr "type" "call")
++   ; With TARGET_MEDIUM_CALLS, plt calls are not predicable.
++   (set_attr "predicable" "no")])
++
++; We make this call specific to the tls symbol to avoid commoning this
++; with calls for other symbols; we want the linker to be able to
++(define_insn "tls_gd_dispatch"
++  [(set (reg:SI R0_REG)
++	(unspec:SI
++	  [(reg:SI R0_REG)
++	   (call (mem:SI (match_operand:SI 0 "register_operand" "Rcq,q,c"))
++		 (const_int 0))
++	   (match_operand:SI 1 "symbolic_operand" "X,X,X")]
++	 UNSPEC_TLS_GD))
++   (clobber (reg:SI RETURN_ADDR_REGNUM))
++   (clobber (reg:DI R10_REG))
++   (clobber (reg:SI R12_REG))]
++  ""
++  ".tls_gd_call %1`jl%!%* [%0]"
++  [(set_attr "type" "call")
++   (set_attr "iscompact" "maybe,false,*")
++   (set_attr "predicable" "no,no,yes")])
++
++;; For thread pointer builtins
++(define_expand "get_thread_pointersi"
++  [(set (match_operand:SI 0 "register_operand") (match_dup 1))]
++ ""
++ "operands[1] = gen_rtx_REG (Pmode, arc_tp_regno);")
++
++(define_expand "set_thread_pointersi"
++  [(set (match_dup 1) (match_operand:SI 0 "register_operand"))]
++ ""
++ "operands[1] = gen_rtx_REG (Pmode, arc_tp_regno);")
++
+ ;; If hardware floating point is available, don't define a negdf pattern;
+ ;; it would be something like:
+ ;;(define_insn "negdf2"
+diff --git a/gcc/config/arc/arc.opt b/gcc/config/arc/arc.opt
+index 2227b7554c30..76f66a2988b2 100644
+--- a/gcc/config/arc/arc.opt
++++ b/gcc/config/arc/arc.opt
+@@ -456,3 +456,10 @@ Enum(arc_fpu) String(fpus_all) Value(FPU_SP | FPU_SC | FPU_SF | FPU_SD)
+ 
+ EnumValue
+ Enum(arc_fpu) String(fpud_all) Value(FPU_SP | FPU_SC | FPU_SF | FPU_SD | FPU_DP | FPU_DC | FPU_DF | FPU_DD)
++
++mtp-regno=
++Target RejectNegative Joined UInteger Var(arc_tp_regno) Init(25)
++Specify thread pointer register number
++
++mtp-regno=none
++Target RejectNegative Var(arc_tp_regno,-1)
+diff --git a/gcc/config/arc/predicates.md b/gcc/config/arc/predicates.md
+index 85bbf8435588..3c657c67f0d3 100644
+--- a/gcc/config/arc/predicates.md
++++ b/gcc/config/arc/predicates.md
+@@ -351,9 +351,12 @@
+   switch (GET_CODE (op))
+     {
+     case SYMBOL_REF :
++      if (SYMBOL_REF_TLS_MODEL (op))
++	return 0;
+     case LABEL_REF :
++      return 1;
+     case CONST :
+-      return (!flag_pic || arc_legitimate_pic_operand_p(op));
++      return arc_legitimate_constant_p (mode, op);
+     case CONST_INT :
+       return (LARGE_INT (INTVAL (op)));
+     case CONST_DOUBLE :
+@@ -451,6 +454,16 @@
+ 	    && (GET_CODE (XEXP (addr, 1)) != PLUS
+ 		|| !CONST_INT_P (XEXP (XEXP (addr, 1), 1))))
+ 	  return 0;
++	/* CONST_INT / CONST_DOUBLE is fine, but the PIC CONST ([..] UNSPEC))
++	   constructs are effectively indexed.  */
++	if (flag_pic)
++	  {
++	    rtx ad0 = addr;
++	    while (GET_CODE (ad0) == PLUS)
++	      ad0 = XEXP (ad0, 0);
++	    if (GET_CODE (ad0) == CONST || GET_CODE (ad0) == UNSPEC)
++	      return 0;
++	  }
+ 	return address_operand (addr, mode);
+       }
+     default :
+diff --git a/gcc/configure b/gcc/configure
+index 954673c1c436..17ca349bdc3e 100755
+--- a/gcc/configure
++++ b/gcc/configure
+@@ -23856,6 +23856,12 @@ foo:	.long	25
+ 	tls_first_minor=13
+ 	tls_as_opt=--fatal-warnings
+ 	;;
++  arc*-*-*)
++    conftest_s='
++	add_s r0,r0, @foo at tpoff'
++	tls_first_major=2
++	tls_first_minor=23
++	;;
+   cris-*-*|crisv32-*-*)
+     conftest_s='
+ 	.section ".tdata","awT", at progbits
+diff --git a/gcc/configure.ac b/gcc/configure.ac
+index 4c65d441e72f..0a1e84f4f1f9 100644
+--- a/gcc/configure.ac
++++ b/gcc/configure.ac
+@@ -3088,6 +3088,12 @@ foo:	.long	25
+ 	tls_first_minor=13
+ 	tls_as_opt=--fatal-warnings
+ 	;;
++  arc*-*-*)
++    conftest_s='
++	add_s r0,r0, @foo at tpoff'
++	tls_first_major=2
++	tls_first_minor=23
++	;;
+   cris-*-*|crisv32-*-*)
+     conftest_s='
+ 	.section ".tdata","awT", at progbits
+diff --git a/gcc/doc/invoke.texi b/gcc/doc/invoke.texi
+index 2ed92858e6c6..e6e725ec1c01 100644
+--- a/gcc/doc/invoke.texi
++++ b/gcc/doc/invoke.texi
+@@ -592,7 +592,7 @@ Objective-C and Objective-C++ Dialects}.
+ -mcrc -mdsp-packa -mdvbf -mlock -mmac-d16 -mmac-24 -mrtsc -mswape @gol
+ -mtelephony -mxy -misize -mannotate-align -marclinux -marclinux_prof @gol
+ -mlong-calls -mmedium-calls -msdata @gol
+--mucb-mcount -mvolatile-cache @gol
++-mucb-mcount -mvolatile-cache -mtp-regno=@var{regno} @gol
+ -malign-call -mauto-modify-reg -mbbit-peephole -mno-brcc @gol
+ -mcase-vector-pcrel -mcompact-casesi -mno-cond-exec -mearly-cbranchsi @gol
+ -mexpand-adddi -mindexed-loads -mlra -mlra-priority-none @gol
+@@ -13341,6 +13341,10 @@ Enable code density instructions for ARC EM, default on for ARC HS.
+ @opindex mll64
+ Enable double load/store operations for ARC HS cores.
+ 
++ at item -mtp-regno=@var{regno}
++ at opindex mtp-regno
++Specify thread pointer register number.
++
+ @item -mmpy-option=@var{multo}
+ @opindex mmpy-option
+ Compile ARCv2 code with a multiplier design option.  @samp{wlh1} is
+-- 
+2.7.4
+
diff --git a/toolchain/gcc/patches/6.3.0/0004-ARC-Don-t-use-drsub-instructions-when-selecting-fpud.patch b/toolchain/gcc/patches/6.3.0/0004-ARC-Don-t-use-drsub-instructions-when-selecting-fpud.patch
new file mode 100644
index 0000000..eb94e25
--- /dev/null
+++ b/toolchain/gcc/patches/6.3.0/0004-ARC-Don-t-use-drsub-instructions-when-selecting-fpud.patch
@@ -0,0 +1,121 @@
+From 0a9f4daa9e9f009fb877f6de89aa3b6504cf2794 Mon Sep 17 00:00:00 2001
+From: claziss <claziss at 138bc75d-0d04-0410-961f-82ee72b054a4>
+Date: Thu, 28 Apr 2016 12:15:06 +0000
+Subject: [PATCH 04/89] [ARC] Don't use drsub* instructions when selecting
+ fpuda.
+
+The double precision floating point assist instructions are not
+implementing the reverse double subtract instruction (drsub) found in
+the FPX extension.
+
+gcc/
+2016-04-28  Claudiu Zissulescu  <claziss at synopsys.com>
+
+	* config/arc/arc.md (cpu_facility): Add fpx variant.
+	(subdf3): Prohibit use reverse sub when assist operations option
+	is enabled.
+	* config/arc/fpx.md (subdf3_insn, *dsubh_peep2_insn): Allow drsub
+	instructions only when FPX is enabled.
+        * testsuite/gcc.target/arc/trsub.c: New test.
+
+git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@235562 138bc75d-0d04-0410-961f-82ee72b054a4
+---
+ gcc/ChangeLog                        |  9 +++++++++
+ gcc/config/arc/arc.md                |  8 +++++++-
+ gcc/config/arc/fpx.md                |  7 ++++---
+ gcc/testsuite/gcc.target/arc/trsub.c | 10 ++++++++++
+ 4 files changed, 30 insertions(+), 4 deletions(-)
+ create mode 100644 gcc/testsuite/gcc.target/arc/trsub.c
+
+diff --git a/gcc/ChangeLog b/gcc/ChangeLog
+index 047bc20a9790..262cf2a4aa24 100644
+--- a/gcc/ChangeLog
++++ b/gcc/ChangeLog
+@@ -1,4 +1,13 @@
+ 2016-04-28  Claudiu Zissulescu  <claziss at synopsys.com>
++
++	* config/arc/arc.md (cpu_facility): Add fpx variant.
++	(subdf3): Prohibit use reverse sub when assist operations option
++	is enabled.
++	* config/arc/fpx.md (subdf3_insn, *dsubh_peep2_insn): Allow drsub
++	instructions only when FPX is enabled.
++	* testsuite/gcc.target/arc/trsub.c: New test.
++
++2016-04-28  Claudiu Zissulescu  <claziss at synopsys.com>
+ 	    Joern Rennecke  <joern.rennecke at embecosm.com>
+ 
+ 	* config/arc/arc-protos.h (arc_legitimize_pic_address): Remove
+diff --git a/gcc/config/arc/arc.md b/gcc/config/arc/arc.md
+index 4a7287b05365..a58b491355a9 100644
+--- a/gcc/config/arc/arc.md
++++ b/gcc/config/arc/arc.md
+@@ -270,7 +270,7 @@
+ 		     - get_attr_length (insn)")))
+ 
+ ; for ARCv2 we need to disable/enable different instruction alternatives
+-(define_attr "cpu_facility" "std,av1,av2"
++(define_attr "cpu_facility" "std,av1,av2,fpx"
+   (const_string "std"))
+ 
+ ; We should consider all the instructions enabled until otherwise
+@@ -282,6 +282,10 @@
+ 	 (and (eq_attr "cpu_facility" "av2")
+ 	      (not (match_test "TARGET_V2")))
+ 	 (const_string "no")
++
++	 (and (eq_attr "cpu_facility" "fpx")
++	      (match_test "TARGET_FP_DP_AX"))
++	 (const_string "no")
+ 	 ]
+ 	(const_string "yes")))
+ 
+@@ -5780,6 +5784,8 @@
+   "
+    if (TARGET_DPFP)
+     {
++     if (TARGET_FP_DP_AX && (GET_CODE (operands[1]) == CONST_DOUBLE))
++       operands[1] = force_reg (DFmode, operands[1]);
+      if ((GET_CODE (operands[1]) == CONST_DOUBLE)
+           || GET_CODE (operands[2]) == CONST_DOUBLE)
+       {
+diff --git a/gcc/config/arc/fpx.md b/gcc/config/arc/fpx.md
+index b79060037489..2e11157cabfb 100644
+--- a/gcc/config/arc/fpx.md
++++ b/gcc/config/arc/fpx.md
+@@ -304,7 +304,8 @@
+      drsubh%F0%F2 0,%H1,%L1
+      drsubh%F0%F2 0,%3,%L1"
+   [(set_attr "type" "dpfp_addsub")
+-  (set_attr "length" "4,8,4,8")])
++   (set_attr "length" "4,8,4,8")
++   (set_attr "cpu_facility" "*,*,fpx,fpx")])
+ 
+ ;; ;; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;; ;; Peephole for following conversion
+@@ -613,5 +614,5 @@
+   drsubh%F0%F2 %H6, %H1, %L1
+   drsubh%F0%F2 %H6, %3, %L1"
+  [(set_attr "type" "dpfp_addsub")
+-  (set_attr "length" "4,8,4,8")]
+-)
++  (set_attr "length" "4,8,4,8")
++  (set_attr "cpu_facility" "*,*,fpx,fpx")])
+diff --git a/gcc/testsuite/gcc.target/arc/trsub.c b/gcc/testsuite/gcc.target/arc/trsub.c
+new file mode 100644
+index 000000000000..031935fdc8f5
+--- /dev/null
++++ b/gcc/testsuite/gcc.target/arc/trsub.c
+@@ -0,0 +1,10 @@
++/* Tests if we generate rsub instructions when compiling using
++   floating point assist instructions.  */
++/* { dg-do compile } */
++/* { dg-options "-mfpu=fpuda -mcpu=arcem" } */
++
++double foo (double a)
++{
++  return ((double) 0.12 - a);
++}
++/* { dg-final { scan-assembler-not "drsub.*" } } */
+-- 
+2.7.4
+
diff --git a/toolchain/gcc/patches/6.3.0/0005-ARC-Fix-FPX-FPUDA-code-gen-when-compiling-for-big-en.patch b/toolchain/gcc/patches/6.3.0/0005-ARC-Fix-FPX-FPUDA-code-gen-when-compiling-for-big-en.patch
new file mode 100644
index 0000000..7ae674c
--- /dev/null
+++ b/toolchain/gcc/patches/6.3.0/0005-ARC-Fix-FPX-FPUDA-code-gen-when-compiling-for-big-en.patch
@@ -0,0 +1,140 @@
+From e1c7cc8f21823d1bbe874912884c4b2cc7f4ba67 Mon Sep 17 00:00:00 2001
+From: claziss <claziss at 138bc75d-0d04-0410-961f-82ee72b054a4>
+Date: Thu, 28 Apr 2016 12:52:04 +0000
+Subject: [PATCH 05/89] [ARC] Fix FPX/FPUDA code gen when compiling for
+ big-endian.
+
+gcc/
+2016-04-28  Claudiu Zissulescu  <claziss at synopsys.com>
+
+	* config/arc/arc.c (arc_process_double_reg_moves): Fix for
+	big-endian compilation.
+	(arc_rtx_costs): Fix high/low naming.
+	* config/arc/arc.md (addf3): Likewise.
+	(subdf3): Likewise.
+	(muldf3): Likewise.
+
+git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@235567 138bc75d-0d04-0410-961f-82ee72b054a4
+---
+ gcc/ChangeLog         |  8 ++++++++
+ gcc/config/arc/arc.c  | 21 ++++++++++++---------
+ gcc/config/arc/arc.md | 18 +++++++++---------
+ 3 files changed, 29 insertions(+), 18 deletions(-)
+
+diff --git a/gcc/ChangeLog b/gcc/ChangeLog
+index 262cf2a4aa24..153194efe9a1 100644
+--- a/gcc/ChangeLog
++++ b/gcc/ChangeLog
+@@ -1,5 +1,13 @@
+ 2016-04-28  Claudiu Zissulescu  <claziss at synopsys.com>
+ 
++	* config/arc/arc.c (arc_process_double_reg_moves): Fix for
++	big-endian compilation.
++	* config/arc/arc.md (addf3): Likewise.
++	(subdf3): Likewise.
++	(muldf3): Likewise.
++
++2016-04-28  Claudiu Zissulescu  <claziss at synopsys.com>
++
+ 	* config/arc/arc.md (cpu_facility): Add fpx variant.
+ 	(subdf3): Prohibit use reverse sub when assist operations option
+ 	is enabled.
+diff --git a/gcc/config/arc/arc.c b/gcc/config/arc/arc.c
+index d40d54deb34a..e7067374e465 100644
+--- a/gcc/config/arc/arc.c
++++ b/gcc/config/arc/arc.c
+@@ -4426,17 +4426,16 @@ arc_rtx_costs (rtx x, machine_mode mode, int outer_code,
+ 
+     case CONST_DOUBLE:
+       {
+-	rtx high, low;
++	rtx first, second;
+ 
+ 	if (TARGET_DPFP)
+ 	  {
+ 	    *total = COSTS_N_INSNS (1);
+ 	    return true;
+ 	  }
+-	/* FIXME: correct the order of high,low */
+-	split_double (x, &high, &low);
+-	*total = COSTS_N_INSNS (!SMALL_INT (INTVAL (high))
+-				+ !SMALL_INT (INTVAL (low)));
++	split_double (x, &first, &second);
++	*total = COSTS_N_INSNS (!SMALL_INT (INTVAL (first))
++				+ !SMALL_INT (INTVAL (second)));
+ 	return true;
+       }
+ 
+@@ -8928,8 +8927,10 @@ arc_process_double_reg_moves (rtx *operands)
+ 	{
+ 	  /* When we have 'mov D, r' or 'mov D, D' then get the target
+ 	     register pair for use with LR insn.  */
+-	  rtx destHigh = simplify_gen_subreg(SImode, dest, DFmode, 4);
+-	  rtx destLow  = simplify_gen_subreg(SImode, dest, DFmode, 0);
++	  rtx destHigh = simplify_gen_subreg (SImode, dest, DFmode,
++					     TARGET_BIG_ENDIAN ? 0 : 4);
++	  rtx destLow  = simplify_gen_subreg (SImode, dest, DFmode,
++					     TARGET_BIG_ENDIAN ? 4 : 0);
+ 
+ 	  /* Produce the two LR insns to get the high and low parts.  */
+ 	  emit_insn (gen_rtx_SET (destHigh,
+@@ -8946,8 +8947,10 @@ arc_process_double_reg_moves (rtx *operands)
+     {
+       /* When we have 'mov r, D' or 'mov D, D' and we have access to the
+ 	 LR insn get the target register pair.  */
+-      rtx srcHigh = simplify_gen_subreg(SImode, src, DFmode, 4);
+-      rtx srcLow  = simplify_gen_subreg(SImode, src, DFmode, 0);
++      rtx srcHigh = simplify_gen_subreg (SImode, src, DFmode,
++					TARGET_BIG_ENDIAN ? 0 : 4);
++      rtx srcLow  = simplify_gen_subreg (SImode, src, DFmode,
++					TARGET_BIG_ENDIAN ? 4 : 0);
+ 
+       emit_insn (gen_rtx_UNSPEC_VOLATILE (Pmode,
+ 					  gen_rtvec (3, dest, srcHigh, srcLow),
+diff --git a/gcc/config/arc/arc.md b/gcc/config/arc/arc.md
+index a58b491355a9..8ec0ce0427ba 100644
+--- a/gcc/config/arc/arc.md
++++ b/gcc/config/arc/arc.md
+@@ -5752,9 +5752,9 @@
+    {
+     if (GET_CODE (operands[2]) == CONST_DOUBLE)
+      {
+-        rtx high, low, tmp;
+-        split_double (operands[2], &low, &high);
+-        tmp = force_reg (SImode, high);
++        rtx first, second, tmp;
++        split_double (operands[2], &first, &second);
++        tmp = force_reg (SImode, TARGET_BIG_ENDIAN ? first : second);
+         emit_insn (gen_adddf3_insn (operands[0], operands[1],
+                                     operands[2], tmp, const0_rtx));
+      }
+@@ -5789,10 +5789,10 @@
+      if ((GET_CODE (operands[1]) == CONST_DOUBLE)
+           || GET_CODE (operands[2]) == CONST_DOUBLE)
+       {
+-        rtx high, low, tmp;
++        rtx first, second, tmp;
+         int const_index = ((GET_CODE (operands[1]) == CONST_DOUBLE) ? 1 : 2);
+-        split_double (operands[const_index], &low, &high);
+-        tmp = force_reg (SImode, high);
++        split_double (operands[const_index], &first, &second);
++        tmp = force_reg (SImode, TARGET_BIG_ENDIAN ? first : second);
+         emit_insn (gen_subdf3_insn (operands[0], operands[1],
+                                     operands[2], tmp, const0_rtx));
+       }
+@@ -5824,9 +5824,9 @@
+     {
+      if (GET_CODE (operands[2]) == CONST_DOUBLE)
+       {
+-        rtx high, low, tmp;
+-        split_double (operands[2], &low, &high);
+-        tmp = force_reg (SImode, high);
++        rtx first, second, tmp;
++        split_double (operands[2], &first, &second);
++        tmp = force_reg (SImode, TARGET_BIG_ENDIAN ? first : second);
+         emit_insn (gen_muldf3_insn (operands[0], operands[1],
+                                     operands[2], tmp, const0_rtx));
+       }
+-- 
+2.7.4
+
diff --git a/toolchain/gcc/patches/6.3.0/0006-ARC-Pass-mfpuda-to-assembler.patch b/toolchain/gcc/patches/6.3.0/0006-ARC-Pass-mfpuda-to-assembler.patch
new file mode 100644
index 0000000..f029a70
--- /dev/null
+++ b/toolchain/gcc/patches/6.3.0/0006-ARC-Pass-mfpuda-to-assembler.patch
@@ -0,0 +1,46 @@
+From 77f712be933a5dd0c93acf6c1e1f43757f8e893a Mon Sep 17 00:00:00 2001
+From: claziss <claziss at 138bc75d-0d04-0410-961f-82ee72b054a4>
+Date: Thu, 28 Apr 2016 13:08:01 +0000
+Subject: [PATCH 06/89] [ARC] Pass mfpuda to assembler.
+
+gcc/
+2016-04-28  Claudiu Zissulescu  <claziss at synopsys.com>
+
+	* config/arc/arc.h (ASM_SPEC): Pass mfpuda to assembler.
+
+git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@235568 138bc75d-0d04-0410-961f-82ee72b054a4
+---
+ gcc/ChangeLog        | 4 ++++
+ gcc/config/arc/arc.h | 2 +-
+ 2 files changed, 5 insertions(+), 1 deletion(-)
+
+diff --git a/gcc/ChangeLog b/gcc/ChangeLog
+index 153194efe9a1..4bc68957046f 100644
+--- a/gcc/ChangeLog
++++ b/gcc/ChangeLog
+@@ -1,5 +1,9 @@
+ 2016-04-28  Claudiu Zissulescu  <claziss at synopsys.com>
+ 
++	* config/arc/arc.h (ASM_SPEC): Pass mfpuda to assembler.
++
++2016-04-28  Claudiu Zissulescu  <claziss at synopsys.com>
++
+ 	* config/arc/arc.c (arc_process_double_reg_moves): Fix for
+ 	big-endian compilation.
+ 	* config/arc/arc.md (addf3): Likewise.
+diff --git a/gcc/config/arc/arc.h b/gcc/config/arc/arc.h
+index de6c6d11974a..37c1afa6712e 100644
+--- a/gcc/config/arc/arc.h
++++ b/gcc/config/arc/arc.h
+@@ -155,7 +155,7 @@ along with GCC; see the file COPYING3.  If not see
+ %{mcpu=ARC700:-mEA} \
+ %{!mcpu=*:" ASM_DEFAULT "} \
+ %{mbarrel-shifter} %{mno-mpy} %{mmul64} %{mmul32x16:-mdsp-packa} %{mnorm} \
+-%{mswap} %{mEA} %{mmin-max} %{mspfp*} %{mdpfp*} \
++%{mswap} %{mEA} %{mmin-max} %{mspfp*} %{mdpfp*} %{mfpu=fpuda*:-mfpuda} \
+ %{msimd} \
+ %{mmac-d16} %{mmac-24} %{mdsp-packa} %{mcrc} %{mdvbf} %{mtelephony} %{mxy} \
+ %{mcpu=ARC700|!mcpu=*:%{mlock}} \
+-- 
+2.7.4
+
diff --git a/toolchain/gcc/patches/6.3.0/0007-2016-04-28-Andrew-Burgess-andrew.burgess-embecosm.co.patch b/toolchain/gcc/patches/6.3.0/0007-2016-04-28-Andrew-Burgess-andrew.burgess-embecosm.co.patch
new file mode 100644
index 0000000..4016f8e
--- /dev/null
+++ b/toolchain/gcc/patches/6.3.0/0007-2016-04-28-Andrew-Burgess-andrew.burgess-embecosm.co.patch
@@ -0,0 +1,128 @@
+From 820d3306c7dd9ce68463f16050cae1edf8bdcc83 Mon Sep 17 00:00:00 2001
+From: amylaar <amylaar at 138bc75d-0d04-0410-961f-82ee72b054a4>
+Date: Thu, 28 Apr 2016 16:59:18 +0000
+Subject: [PATCH 07/89] 2016-04-28  Andrew Burgess 
+ <andrew.burgess at embecosm.com>
+
+        * common/config/arc/arc-common.c (arc_handle_option): Add NPS400
+        support, setup defaults.
+        * config/arc/arc-opts.h (enum processor_type): Add NPS400.
+        * config/arc/arc.c (arc_init): Add NPS400 support.
+        * config/arc/arc.h (CPP_SPEC): Add NPS400 defines.
+        (TARGET_ARC700): NPS400 is also an ARC700.
+        * config/arc/arc.opt: Add NPS400 options to -mcpu=.
+
+git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@235584 138bc75d-0d04-0410-961f-82ee72b054a4
+---
+ gcc/ChangeLog                      | 10 ++++++++++
+ gcc/common/config/arc/arc-common.c |  4 ++++
+ gcc/config/arc/arc-opts.h          |  1 +
+ gcc/config/arc/arc.c               |  5 +++++
+ gcc/config/arc/arc.h               |  5 ++++-
+ gcc/config/arc/arc.opt             |  6 ++++++
+ 6 files changed, 30 insertions(+), 1 deletion(-)
+
+diff --git a/gcc/ChangeLog b/gcc/ChangeLog
+index 4bc68957046f..f5d047e5fe64 100644
+--- a/gcc/ChangeLog
++++ b/gcc/ChangeLog
+@@ -1,3 +1,13 @@
++2016-04-28  Andrew Burgess  <andrew.burgess at embecosm.com>
++
++	* common/config/arc/arc-common.c (arc_handle_option): Add NPS400
++	support, setup defaults.
++	* config/arc/arc-opts.h (enum processor_type): Add NPS400.
++	* config/arc/arc.c (arc_init): Add NPS400 support.
++	* config/arc/arc.h (CPP_SPEC): Add NPS400 defines.
++	(TARGET_ARC700): NPS400 is also an ARC700.
++	* config/arc/arc.opt: Add NPS400 options to -mcpu=.
++
+ 2016-04-28  Claudiu Zissulescu  <claziss at synopsys.com>
+ 
+ 	* config/arc/arc.h (ASM_SPEC): Pass mfpuda to assembler.
+diff --git a/gcc/common/config/arc/arc-common.c b/gcc/common/config/arc/arc-common.c
+index 64fb053142c9..f5b9c6d3cc98 100644
+--- a/gcc/common/config/arc/arc-common.c
++++ b/gcc/common/config/arc/arc-common.c
+@@ -83,6 +83,10 @@ arc_handle_option (struct gcc_options *opts, struct gcc_options *opts_set,
+ 
+       switch (value)
+ 	{
++	case PROCESSOR_NPS400:
++	  if (! (opts_set->x_TARGET_CASE_VECTOR_PC_RELATIVE) )
++	    opts->x_TARGET_CASE_VECTOR_PC_RELATIVE = 1;
++	  /* Fall through */
+ 	case PROCESSOR_ARC600:
+ 	case PROCESSOR_ARC700:
+ 	  if (! (opts_set->x_target_flags & MASK_BARREL_SHIFTER) )
+diff --git a/gcc/config/arc/arc-opts.h b/gcc/config/arc/arc-opts.h
+index 1e11ebc41ffb..cbd78985dd8b 100644
+--- a/gcc/config/arc/arc-opts.h
++++ b/gcc/config/arc/arc-opts.h
+@@ -24,6 +24,7 @@ enum processor_type
+   PROCESSOR_ARC600,
+   PROCESSOR_ARC601,
+   PROCESSOR_ARC700,
++  PROCESSOR_NPS400,
+   PROCESSOR_ARCEM,
+   PROCESSOR_ARCHS
+ };
+diff --git a/gcc/config/arc/arc.c b/gcc/config/arc/arc.c
+index e7067374e465..e3744b8c971e 100644
+--- a/gcc/config/arc/arc.c
++++ b/gcc/config/arc/arc.c
+@@ -690,6 +690,11 @@ arc_init (void)
+       tune_dflt = TUNE_ARC700_4_2_STD;
+       break;
+ 
++    case PROCESSOR_NPS400:
++      arc_cpu_string = "NPS400";
++      tune_dflt = TUNE_ARC700_4_2_STD;
++      break;
++
+     case PROCESSOR_ARCEM:
+       arc_cpu_string = "EM";
+       break;
+diff --git a/gcc/config/arc/arc.h b/gcc/config/arc/arc.h
+index 37c1afa6712e..b14352c3e262 100644
+--- a/gcc/config/arc/arc.h
++++ b/gcc/config/arc/arc.h
+@@ -138,6 +138,8 @@ along with GCC; see the file COPYING3.  If not see
+ %{mdsp-packa:-D__Xdsp_packa} %{mcrc:-D__Xcrc} %{mdvbf:-D__Xdvbf} \
+ %{mtelephony:-D__Xtelephony} %{mxy:-D__Xxy} %{mmul64: -D__Xmult32} \
+ %{mlock:-D__Xlock} %{mswape:-D__Xswape} %{mrtsc:-D__Xrtsc} \
++%{mcpu=NPS400:-D__NPS400__} \
++%{mcpu=nps400:-D__NPS400__} \
+ "
+ 
+ #define CC1_SPEC "\
+@@ -305,7 +307,8 @@ along with GCC; see the file COPYING3.  If not see
+ 
+ #define TARGET_ARC600 (arc_cpu == PROCESSOR_ARC600)
+ #define TARGET_ARC601 (arc_cpu == PROCESSOR_ARC601)
+-#define TARGET_ARC700 (arc_cpu == PROCESSOR_ARC700)
++#define TARGET_ARC700 (arc_cpu == PROCESSOR_ARC700	\
++		       || arc_cpu == PROCESSOR_NPS400)
+ #define TARGET_EM     (arc_cpu == PROCESSOR_ARCEM)
+ #define TARGET_HS     (arc_cpu == PROCESSOR_ARCHS)
+ #define TARGET_V2							\
+diff --git a/gcc/config/arc/arc.opt b/gcc/config/arc/arc.opt
+index 76f66a2988b2..45bb6a6167d3 100644
+--- a/gcc/config/arc/arc.opt
++++ b/gcc/config/arc/arc.opt
+@@ -189,6 +189,12 @@ EnumValue
+ Enum(processor_type) String(arc700) Value(PROCESSOR_ARC700)
+ 
+ EnumValue
++Enum(processor_type) String(nps400) Value(PROCESSOR_NPS400)
++
++EnumValue
++Enum(processor_type) String(NPS400) Value(PROCESSOR_NPS400)
++
++EnumValue
+ Enum(processor_type) String(ARCEM) Value(PROCESSOR_ARCEM)
+ 
+ EnumValue
+-- 
+2.7.4
+
diff --git a/toolchain/gcc/patches/6.3.0/0008-2016-04-28-Andrew-Burgess-andrew.burgess-embecosm.co.patch b/toolchain/gcc/patches/6.3.0/0008-2016-04-28-Andrew-Burgess-andrew.burgess-embecosm.co.patch
new file mode 100644
index 0000000..1657dbb
--- /dev/null
+++ b/toolchain/gcc/patches/6.3.0/0008-2016-04-28-Andrew-Burgess-andrew.burgess-embecosm.co.patch
@@ -0,0 +1,78 @@
+From aaa5e66450e85915f9190176a8f2fcb453d6bca4 Mon Sep 17 00:00:00 2001
+From: amylaar <amylaar at 138bc75d-0d04-0410-961f-82ee72b054a4>
+Date: Thu, 28 Apr 2016 17:16:05 +0000
+Subject: [PATCH 08/89] 2016-04-28  Andrew Burgess 
+ <andrew.burgess at embecosm.com>
+
+        * config/arc/constraints.md (Usd): Convert to define_constraint.
+        (Us<): Likewise.
+        (Us>): Likewise.
+
+git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@235587 138bc75d-0d04-0410-961f-82ee72b054a4
+---
+ gcc/ChangeLog                 |  6 ++++++
+ gcc/config/arc/constraints.md | 18 +++++++++++-------
+ 2 files changed, 17 insertions(+), 7 deletions(-)
+
+diff --git a/gcc/ChangeLog b/gcc/ChangeLog
+index f5d047e5fe64..8a90a7836e43 100644
+--- a/gcc/ChangeLog
++++ b/gcc/ChangeLog
+@@ -1,5 +1,11 @@
+ 2016-04-28  Andrew Burgess  <andrew.burgess at embecosm.com>
+ 
++	* config/arc/constraints.md (Usd): Convert to define_constraint.
++	(Us<): Likewise.
++	(Us>): Likewise.
++
++2016-04-28  Andrew Burgess  <andrew.burgess at embecosm.com>
++
+ 	* common/config/arc/arc-common.c (arc_handle_option): Add NPS400
+ 	support, setup defaults.
+ 	* config/arc/arc-opts.h (enum processor_type): Add NPS400.
+diff --git a/gcc/config/arc/constraints.md b/gcc/config/arc/constraints.md
+index 668b60a6b3a6..b6954ad9456a 100644
+--- a/gcc/config/arc/constraints.md
++++ b/gcc/config/arc/constraints.md
+@@ -269,11 +269,15 @@
+   (and (match_code "mem")
+        (match_test "compact_store_memory_operand (op, VOIDmode)")))
+ 
+-(define_memory_constraint "Usd"
+-  "@internal
+-   A valid _small-data_ memory operand for ARCompact instructions"
+-  (and (match_code "mem")
+-       (match_test "compact_sda_memory_operand (op, VOIDmode)")))
++; Don't use define_memory_constraint here as the relocation patching
++; for small data symbols only works within a ld/st instruction and
++; define_memory_constraint may result in the address being calculated
++; into a register first.
++(define_constraint "Usd"
++   "@internal
++    A valid _small-data_ memory operand for ARCompact instructions"
++   (and (match_code "mem")
++        (match_test "compact_sda_memory_operand (op, VOIDmode)")))
+ 
+ (define_memory_constraint "Usc"
+   "@internal
+@@ -283,7 +287,7 @@
+ ;; ??? the assembler rejects stores of immediates to small data.
+        (match_test "!compact_sda_memory_operand (op, VOIDmode)")))
+ 
+-(define_memory_constraint "Us<"
++(define_constraint "Us<"
+   "@internal
+    Stack pre-decrement"
+   (and (match_code "mem")
+@@ -291,7 +295,7 @@
+        (match_test "REG_P (XEXP (XEXP (op, 0), 0))")
+        (match_test "REGNO (XEXP (XEXP (op, 0), 0)) == SP_REG")))
+ 
+-(define_memory_constraint "Us>"
++(define_constraint "Us>"
+   "@internal
+    Stack post-increment"
+   (and (match_code "mem")
+-- 
+2.7.4
+
diff --git a/toolchain/gcc/patches/6.3.0/0009-2016-04-28-Joern-Rennecke-joern.rennecke-embecosm.co.patch b/toolchain/gcc/patches/6.3.0/0009-2016-04-28-Joern-Rennecke-joern.rennecke-embecosm.co.patch
new file mode 100644
index 0000000..c8ae0c2
--- /dev/null
+++ b/toolchain/gcc/patches/6.3.0/0009-2016-04-28-Joern-Rennecke-joern.rennecke-embecosm.co.patch
@@ -0,0 +1,701 @@
+From d23300e56230f917866761c4d6502a578d7abeec Mon Sep 17 00:00:00 2001
+From: amylaar <amylaar at 138bc75d-0d04-0410-961f-82ee72b054a4>
+Date: Thu, 28 Apr 2016 18:21:42 +0000
+Subject: [PATCH 09/89] 2016-04-28  Joern Rennecke 
+ <joern.rennecke at embecosm.com>             Andrew Burgess 
+ <andrew.burgess at embecosm.com> gcc:         * config/arc/arc.h
+ (SYMBOL_FLAG_CMEM): Define.         (TARGET_NPS_CMEM_DEFAULT): Provide
+ default definition.         * config/arc/arc.c (arc_address_cost): Return 0
+ for cmem_address.         (arc_encode_section_info): Set SYMBOL_FLAG_CMEM
+ where indicated.         * config/arc/arc.opt (mcmem): New option.         *
+ config/arc/arc.md (*extendqihi2_i): Add r/Uex alternative,         supply
+ length for r/m alternative.         (*extendqisi2_ac): Likewise.        
+ (*extendhisi2_i): Add r/Uex alternative, supply length for r/m and        
+ r/Uex alternative.         (movqi_insn): Add r/Ucm and Ucm/?Rac alternatives.
+         (movhi_insn): Likewise.         (movsi_insn): Add r/Ucm,Ucm/w
+ alternatives.         (*zero_extendqihi2_i): Add r/Ucm alternative.        
+ (*zero_extendqisi2_ac): Likewise.         (*zero_extendhisi2_i): Likewise.   
+      * config/arc/constraints.md (Uex): New memory constraint.         (Ucm):
+ New define_constraint.         * config/arc/predicates.md
+ (long_immediate_loadstore_operand):         Return 0 for MEM with
+ cmem_address address.         (cmem_address_0): New predicates.        
+ (cmem_address_1): Likewise.         (cmem_address_2): Likewise.        
+ (cmem_address): Likewise. gcc/testsuite:         * gcc.target/arc/cmem-1.c:
+ New file.         * gcc.target/arc/cmem-2.c: New file.         *
+ gcc.target/arc/cmem-3.c: New file.         * gcc.target/arc/cmem-4.c: New
+ file.         * gcc.target/arc/cmem-5.c: New file.         *
+ gcc.target/arc/cmem-6.c: New file.         * gcc.target/arc/cmem-7.c: New
+ file.         * gcc.target/arc/cmem-ld.inc: New file.         *
+ gcc.target/arc/cmem-st.inc: New file.
+
+---
+ gcc/ChangeLog                            |  35 ++++++++++
+ gcc/config/arc/arc.c                     |  20 ++++++
+ gcc/config/arc/arc.h                     |   9 +++
+ gcc/config/arc/arc.md                    | 115 +++++++++++++++++--------------
+ gcc/config/arc/arc.opt                   |   8 +++
+ gcc/config/arc/constraints.md            |  14 +++-
+ gcc/config/arc/predicates.md             |  19 +++++
+ gcc/testsuite/ChangeLog                  |  13 ++++
+ gcc/testsuite/gcc.target/arc/cmem-1.c    |  10 +++
+ gcc/testsuite/gcc.target/arc/cmem-2.c    |  10 +++
+ gcc/testsuite/gcc.target/arc/cmem-3.c    |  10 +++
+ gcc/testsuite/gcc.target/arc/cmem-4.c    |  10 +++
+ gcc/testsuite/gcc.target/arc/cmem-5.c    |  10 +++
+ gcc/testsuite/gcc.target/arc/cmem-6.c    |  10 +++
+ gcc/testsuite/gcc.target/arc/cmem-7.c    |  26 +++++++
+ gcc/testsuite/gcc.target/arc/cmem-ld.inc |  16 +++++
+ gcc/testsuite/gcc.target/arc/cmem-st.inc |  18 +++++
+ 17 files changed, 302 insertions(+), 51 deletions(-)
+ create mode 100644 gcc/testsuite/gcc.target/arc/cmem-1.c
+ create mode 100644 gcc/testsuite/gcc.target/arc/cmem-2.c
+ create mode 100644 gcc/testsuite/gcc.target/arc/cmem-3.c
+ create mode 100644 gcc/testsuite/gcc.target/arc/cmem-4.c
+ create mode 100644 gcc/testsuite/gcc.target/arc/cmem-5.c
+ create mode 100644 gcc/testsuite/gcc.target/arc/cmem-6.c
+ create mode 100644 gcc/testsuite/gcc.target/arc/cmem-7.c
+ create mode 100644 gcc/testsuite/gcc.target/arc/cmem-ld.inc
+ create mode 100644 gcc/testsuite/gcc.target/arc/cmem-st.inc
+
+diff --git a/gcc/ChangeLog b/gcc/ChangeLog
+index 8a90a7836e43..f0d877721dd3 100644
+--- a/gcc/ChangeLog
++++ b/gcc/ChangeLog
+@@ -1,3 +1,38 @@
++2016-04-28  Joern Rennecke  <joern.rennecke at embecosm.com>
++	    Andrew Burgess  <andrew.burgess at embecosm.com>
++
++	* config/arc/constraints.md (Usd): Convert to define_constraint.
++	(Us<): Likewise.
++	(Us>): Likewise.
++
++2016-04-28  Joern Rennecke  <joern.rennecke at embecosm.com>
++	    Andrew Burgess  <andrew.burgess at embecosm.com>
++
++	* config/arc/arc.h (SYMBOL_FLAG_CMEM): Define.
++	(TARGET_NPS_CMEM_DEFAULT): Provide default definition.
++	* config/arc/arc.c (arc_address_cost): Return 0 for cmem_address.
++	(arc_encode_section_info): Set SYMBOL_FLAG_CMEM where indicated.
++	* config/arc/arc.opt (mcmem): New option.
++	* config/arc/arc.md (*extendqihi2_i): Add r/Uex alternative,
++	supply length for r/m alternative.
++	(*extendqisi2_ac): Likewise.
++	(*extendhisi2_i): Add r/Uex alternative, supply length for r/m and
++	r/Uex alternative.
++	(movqi_insn): Add r/Ucm and Ucm/?Rac alternatives.
++	(movhi_insn): Likewise.
++	(movsi_insn): Add r/Ucm,Ucm/w alternatives.
++	(*zero_extendqihi2_i): Add r/Ucm alternative.
++	(*zero_extendqisi2_ac): Likewise.
++	(*zero_extendhisi2_i): Likewise.
++	* config/arc/constraints.md (Uex): New memory constraint.
++	(Ucm): New define_constraint.
++	* config/arc/predicates.md (long_immediate_loadstore_operand):
++	Return 0 for MEM with cmem_address address.
++	(cmem_address_0): New predicates.
++	(cmem_address_1): Likewise.
++	(cmem_address_2): Likewise.
++	(cmem_address): Likewise.
++
+ 2016-04-28  Andrew Burgess  <andrew.burgess at embecosm.com>
+ 
+ 	* config/arc/constraints.md (Usd): Convert to define_constraint.
+diff --git a/gcc/config/arc/arc.c b/gcc/config/arc/arc.c
+index e3744b8c971e..ca9d31ceee95 100644
+--- a/gcc/config/arc/arc.c
++++ b/gcc/config/arc/arc.c
+@@ -1843,6 +1843,8 @@ arc_address_cost (rtx addr, machine_mode, addr_space_t, bool speed)
+     case LABEL_REF :
+     case SYMBOL_REF :
+     case CONST :
++      if (TARGET_NPS_CMEM && cmem_address (addr, SImode))
++	return 0;
+       /* Most likely needs a LIMM.  */
+       return COSTS_N_INSNS (1);
+ 
+@@ -4337,6 +4339,24 @@ arc_encode_section_info (tree decl, rtx rtl, int first)
+ 
+       SYMBOL_REF_FLAGS (symbol) = flags;
+     }
++  else if (TREE_CODE (decl) == VAR_DECL)
++    {
++      rtx symbol = XEXP (rtl, 0);
++
++      tree attr = (TREE_TYPE (decl) != error_mark_node
++		   ? DECL_ATTRIBUTES (decl) : NULL_TREE);
++
++      tree sec_attr = lookup_attribute ("section", attr);
++      if (sec_attr)
++	{
++	  const char *sec_name
++	    = TREE_STRING_POINTER (TREE_VALUE (TREE_VALUE (sec_attr)));
++	  if (strcmp (sec_name, ".cmem") == 0
++	      || strcmp (sec_name, ".cmem_shared") == 0
++	      || strcmp (sec_name, ".cmem_private") == 0)
++	    SYMBOL_REF_FLAGS (symbol) |= SYMBOL_FLAG_CMEM;
++	}
++    }
+ }
+ 
+ /* This is how to output a definition of an internal numbered label where
+diff --git a/gcc/config/arc/arc.h b/gcc/config/arc/arc.h
+index b14352c3e262..a17d41092507 100644
+--- a/gcc/config/arc/arc.h
++++ b/gcc/config/arc/arc.h
+@@ -37,6 +37,7 @@ along with GCC; see the file COPYING3.  If not see
+ #define SYMBOL_FLAG_SHORT_CALL	(SYMBOL_FLAG_MACH_DEP << 0)
+ #define SYMBOL_FLAG_MEDIUM_CALL	(SYMBOL_FLAG_MACH_DEP << 1)
+ #define SYMBOL_FLAG_LONG_CALL	(SYMBOL_FLAG_MACH_DEP << 2)
++#define SYMBOL_FLAG_CMEM	(SYMBOL_FLAG_MACH_DEP << 3)
+ 
+ /* Check if this symbol has a long_call attribute in its declaration */
+ #define SYMBOL_REF_LONG_CALL_P(X)	\
+@@ -321,6 +322,14 @@ along with GCC; see the file COPYING3.  If not see
+ #define MULTILIB_DEFAULTS { "mARC700" }
+ #endif
+ 
++#ifndef UNALIGNED_ACCESS_DEFAULT
++#define UNALIGNED_ACCESS_DEFAULT 0
++#endif
++
++#ifndef TARGET_NPS_CMEM_DEFAULT
++#define TARGET_NPS_CMEM_DEFAULT 0
++#endif
++
+ /* Target machine storage layout.  */
+ 
+ /* We want zero_extract to mean the same
+diff --git a/gcc/config/arc/arc.md b/gcc/config/arc/arc.md
+index 8ec0ce0427ba..93a2cad7dfa6 100644
+--- a/gcc/config/arc/arc.md
++++ b/gcc/config/arc/arc.md
+@@ -620,8 +620,8 @@
+ ; The iscompact attribute allows the epilogue expander to know for which
+ ; insns it should lengthen the return insn.
+ (define_insn "*movqi_insn"
+-  [(set (match_operand:QI 0 "move_dest_operand" "=Rcq,Rcq#q,w, w,w,???w, w,Rcq,S,!*x,r,m,???m")
+-	(match_operand:QI 1 "move_src_operand"   "cL,cP,Rcq#q,cL,I,?Rac,?i,T,Rcq,Usd,m,c,?Rac"))]
++  [(set (match_operand:QI 0 "move_dest_operand" "=Rcq,Rcq#q,w,w,w,???w,w,Rcq,S,!*x,r,r,Ucm,m,???m")
++	(match_operand:QI 1 "move_src_operand"  "cL,cP,Rcq#q,cL,I,?Rac,?i,T,Rcq,Usd,Ucm,m,?Rac,c,?Rac"))]
+   "register_operand (operands[0], QImode)
+    || register_operand (operands[1], QImode)"
+   "@
+@@ -635,13 +635,15 @@
+    ldb%? %0,%1%&
+    stb%? %1,%0%&
+    ldb%? %0,%1%&
++   xldb%U1 %0,%1
+    ldb%U1%V1 %0,%1
++   xstb%U0 %1,%0
+    stb%U0%V0 %1,%0
+    stb%U0%V0 %1,%0"
+-  [(set_attr "type" "move,move,move,move,move,move,move,load,store,load,load,store,store")
+-   (set_attr "iscompact" "maybe,maybe,maybe,false,false,false,false,true,true,true,false,false,false")
+-   (set_attr "predicable" "yes,no,yes,yes,no,yes,yes,no,no,no,no,no,no")
+-   (set_attr "cpu_facility" "*,*,av1,*,*,*,*,*,*,*,*,*,*")])
++  [(set_attr "type" "move,move,move,move,move,move,move,load,store,load,load,load,store,store,store")
++   (set_attr "iscompact" "maybe,maybe,maybe,false,false,false,false,true,true,true,false,false,false,false,false")
++   (set_attr "predicable" "yes,no,yes,yes,no,yes,yes,no,no,no,no,no,no,no,no")
++   (set_attr "cpu_facility" "*,*,av1,*,*,*,*,*,*,*,*,*,*,*,*")])
+ 
+ (define_expand "movhi"
+   [(set (match_operand:HI 0 "move_dest_operand" "")
+@@ -650,8 +652,8 @@
+   "if (prepare_move_operands (operands, HImode)) DONE;")
+ 
+ (define_insn "*movhi_insn"
+-  [(set (match_operand:HI 0 "move_dest_operand" "=Rcq,Rcq#q,w, w,w,???w,Rcq#q,w,Rcq,S,r,m,???m,VUsc")
+-	(match_operand:HI 1 "move_src_operand"   "cL,cP,Rcq#q,cL,I,?Rac,  ?i,?i,T,Rcq,m,c,?Rac,i"))]
++  [(set (match_operand:HI 0 "move_dest_operand" "=Rcq,Rcq#q,w,w,w,???w,Rcq#q,w,Rcq,S,r,r,Ucm,m,???m,VUsc")
++	(match_operand:HI 1 "move_src_operand" "cL,cP,Rcq#q,cL,I,?Rac,?i,?i,T,Rcq,Ucm,m,?Rac,c,?Rac,i"))]
+   "register_operand (operands[0], HImode)
+    || register_operand (operands[1], HImode)
+    || (CONSTANT_P (operands[1])
+@@ -670,14 +672,16 @@
+    mov%? %0,%S1
+    ld%_%? %0,%1%&
+    st%_%? %1,%0%&
++   xld%_%U1 %0,%1
+    ld%_%U1%V1 %0,%1
++   xst%_%U0 %1,%0
+    st%_%U0%V0 %1,%0
+    st%_%U0%V0 %1,%0
+    st%_%U0%V0 %S1,%0"
+-  [(set_attr "type" "move,move,move,move,move,move,move,move,load,store,load,store,store,store")
+-   (set_attr "iscompact" "maybe,maybe,maybe,false,false,false,maybe_limm,false,true,true,false,false,false,false")
+-   (set_attr "predicable" "yes,no,yes,yes,no,yes,yes,yes,no,no,no,no,no,no")
+-   (set_attr "cpu_facility" "*,*,av1,*,*,*,*,*,*,*,*,*,*,*")])
++  [(set_attr "type" "move,move,move,move,move,move,move,move,load,store,load,load,store,store,store,store")
++   (set_attr "iscompact" "maybe,maybe,maybe,false,false,false,maybe_limm,false,true,true,false,false,false,false,false,false")
++   (set_attr "predicable" "yes,no,yes,yes,no,yes,yes,yes,no,no,no,no,no,no,no,no")
++   (set_attr "cpu_facility" "*,*,av1,*,*,*,*,*,*,*,*,*,*,*,*,*")])
+ 
+ (define_expand "movsi"
+   [(set (match_operand:SI 0 "move_dest_operand" "")
+@@ -696,8 +700,8 @@
+ ; insns it should lengthen the return insn.
+ ; N.B. operand 1 of alternative 7 expands into pcl,symbol at gotpc .
+ (define_insn "*movsi_insn"
+-  [(set (match_operand:SI 0 "move_dest_operand" "=Rcq,Rcq#q,w, w,w,  w,???w, ?w,  w,Rcq#q, w,Rcq,  S,Us<,RcqRck,!*x,r,m,???m,VUsc")
+-	(match_operand:SI 1 "move_src_operand"  " cL,cP,Rcq#q,cL,I,Crr,?Rac,Cpc,Clb,?Cal,?Cal,T,Rcq,RcqRck,Us>,Usd,m,c,?Rac,C32"))]
++  [(set (match_operand:SI 0 "move_dest_operand" "=Rcq,Rcq#q,w, w,w,  w,???w, ?w,  w,Rcq#q, w,Rcq,  S,Us<,RcqRck,!*x,r,r,Ucm,m,???m,VUsc")
++	(match_operand:SI 1 "move_src_operand"  " cL,cP,Rcq#q,cL,I,Crr,?Rac,Cpc,Clb,?Cal,?Cal,T,Rcq,RcqRck,Us>,Usd,Ucm,m,w,c,?Rac,C32"))]
+   "register_operand (operands[0], SImode)
+    || register_operand (operands[1], SImode)
+    || (CONSTANT_P (operands[1])
+@@ -722,17 +726,19 @@
+    * return arc_short_long (insn, \"push%? %1%&\", \"st%U0 %1,%0%&\");
+    * return arc_short_long (insn, \"pop%? %0%&\",  \"ld%U1 %0,%1%&\");
+    ld%? %0,%1%&		;15
+-   ld%U1%V1 %0,%1	;16
+-   st%U0%V0 %1,%0       ;17
+-   st%U0%V0 %1,%0       ;18
+-   st%U0%V0 %S1,%0      ;19"
+-  [(set_attr "type" "move,move,move,move,move,two_cycle_core,move,binary,binary,move,move,load,store,store,load,load,load,store,store,store")
+-   (set_attr "iscompact" "maybe,maybe,maybe,false,false,false,false,false,false,maybe_limm,false,true,true,true,true,true,false,false,false,false")
++   xld%U1 %0,%1         ;16
++   ld%U1%V1 %0,%1	;17
++   xst%U0 %1,%0         ;18
++   st%U0%V0 %1,%0       ;19
++   st%U0%V0 %1,%0       ;20
++   st%U0%V0 %S1,%0      ;21"
++  [(set_attr "type" "move,move,move,move,move,two_cycle_core,move,binary,binary,move,move,load,store,store,load,load,load,load,store,store,store,store")
++   (set_attr "iscompact" "maybe,maybe,maybe,false,false,false,false,false,false,maybe_limm,false,true,true,true,true,true,false,false,false,false,false,false")
+    ; Use default length for iscompact to allow for COND_EXEC.  But set length
+    ; of Crr to 4.
+-   (set_attr "length" "*,*,*,4,4,4,4,8,8,*,8,*,*,*,*,*,*,*,*,8")
+-   (set_attr "predicable" "yes,no,yes,yes,no,no,yes,no,no,yes,yes,no,no,no,no,no,no,no,no,no")
+-   (set_attr "cpu_facility" "*,*,av1,*,*,*,*,*,*,*,*,*,*,*,*,*,*,*,*,*")])
++   (set_attr "length" "*,*,*,4,4,4,4,8,8,*,8,*,*,*,*,*,4,*,4,*,*,8")
++   (set_attr "predicable" "yes,no,yes,yes,no,no,yes,no,no,yes,yes,no,no,no,no,no,no,no,no,no,no,no")
++   (set_attr "cpu_facility" "*,*,av1,*,*,*,*,*,*,*,*,*,*,*,*,*,*,*,*,*,*,*")])
+ 
+ ;; Sometimes generated by the epilogue code.  We don't want to
+ ;; recognize these addresses in general, because the limm is costly,
+@@ -1459,18 +1465,19 @@
+ 
+ 
+ (define_insn "*zero_extendqihi2_i"
+-  [(set (match_operand:HI 0 "dest_reg_operand" "=Rcq,Rcq#q,Rcw,w,r")
+-	(zero_extend:HI (match_operand:QI 1 "nonvol_nonimm_operand" "0,Rcq#q,0,c,m")))]
++  [(set (match_operand:HI 0 "dest_reg_operand" "=Rcq,Rcq#q,Rcw,w,r,r")
++	(zero_extend:HI (match_operand:QI 1 "nonvol_nonimm_operand" "0,Rcq#q,0,c,Ucm,m")))]
+   ""
+   "@
+    extb%? %0,%1%&
+    extb%? %0,%1%&
+    bmsk%? %0,%1,7
+    extb %0,%1
++   xldb%U1 %0,%1
+    ldb%U1 %0,%1"
+-  [(set_attr "type" "unary,unary,unary,unary,load")
+-   (set_attr "iscompact" "maybe,true,false,false,false")
+-   (set_attr "predicable" "no,no,yes,no,no")])
++  [(set_attr "type" "unary,unary,unary,unary,load,load")
++   (set_attr "iscompact" "maybe,true,false,false,false,false")
++   (set_attr "predicable" "no,no,yes,no,no,no")])
+ 
+ (define_expand "zero_extendqihi2"
+   [(set (match_operand:HI 0 "dest_reg_operand" "")
+@@ -1480,8 +1487,8 @@
+ )
+ 
+ (define_insn "*zero_extendqisi2_ac"
+-  [(set (match_operand:SI 0 "dest_reg_operand" "=Rcq,Rcq#q,Rcw,w,qRcq,!*x,r")
+-	(zero_extend:SI (match_operand:QI 1 "nonvol_nonimm_operand" "0,Rcq#q,0,c,T,Usd,m")))]
++  [(set (match_operand:SI 0 "dest_reg_operand" "=Rcq,Rcq#q,Rcw,w,qRcq,!*x,r,r")
++	(zero_extend:SI (match_operand:QI 1 "nonvol_nonimm_operand" "0,Rcq#q,0,c,T,Usd,Ucm,m")))]
+   ""
+   "@
+    extb%? %0,%1%&
+@@ -1490,10 +1497,11 @@
+    extb %0,%1
+    ldb%? %0,%1%&
+    ldb%? %0,%1%&
++   xldb%U1 %0,%1
+    ldb%U1 %0,%1"
+-  [(set_attr "type" "unary,unary,unary,unary,load,load,load")
+-   (set_attr "iscompact" "maybe,true,false,false,true,true,false")
+-   (set_attr "predicable" "no,no,yes,no,no,no,no")])
++  [(set_attr "type" "unary,unary,unary,unary,load,load,load,load")
++   (set_attr "iscompact" "maybe,true,false,false,true,true,false,false")
++   (set_attr "predicable" "no,no,yes,no,no,no,no,no")])
+ 
+ (define_expand "zero_extendqisi2"
+   [(set (match_operand:SI 0 "dest_reg_operand" "")
+@@ -1503,8 +1511,8 @@
+ )
+ 
+ (define_insn "*zero_extendhisi2_i"
+-  [(set (match_operand:SI 0 "dest_reg_operand" "=Rcq,q,Rcw,w,!x,Rcqq,r")
+-	(zero_extend:SI (match_operand:HI 1 "nonvol_nonimm_operand" "0,q,0,c,Usd,Usd,m")))]
++  [(set (match_operand:SI 0 "dest_reg_operand" "=Rcq,q,Rcw,w,!x,Rcqq,r,r")
++	(zero_extend:SI (match_operand:HI 1 "nonvol_nonimm_operand" "0,q,0,c,Usd,Usd,Ucm,m")))]
+   ""
+   "@
+    ext%_%? %0,%1%&
+@@ -1513,10 +1521,11 @@
+    ext%_ %0,%1
+    ld%_%? %0,%1%&
+    ld%_%U1 %0,%1
++   * return TARGET_EM ? \"xldh%U1%V1 %0,%1\" : \"xldw%U1 %0,%1\";
+    ld%_%U1%V1 %0,%1"
+-  [(set_attr "type" "unary,unary,unary,unary,load,load,load")
+-   (set_attr "iscompact" "maybe,true,false,false,true,false,false")
+-   (set_attr "predicable" "no,no,yes,no,no,no,no")])
++  [(set_attr "type" "unary,unary,unary,unary,load,load,load,load")
++   (set_attr "iscompact" "maybe,true,false,false,true,false,false,false")
++   (set_attr "predicable" "no,no,yes,no,no,no,no,no")])
+ 
+ 
+ (define_expand "zero_extendhisi2"
+@@ -1529,15 +1538,17 @@
+ ;; Sign extension instructions.
+ 
+ (define_insn "*extendqihi2_i"
+-  [(set (match_operand:HI 0 "dest_reg_operand" "=Rcqq,r,r")
+-	(sign_extend:HI (match_operand:QI 1 "nonvol_nonimm_operand" "Rcqq,r,m")))]
++  [(set (match_operand:HI 0 "dest_reg_operand" "=Rcqq,r,r,r")
++	(sign_extend:HI (match_operand:QI 1 "nonvol_nonimm_operand" "Rcqq,r,Uex,m")))]
+   ""
+   "@
+    sexb%? %0,%1%&
+    sexb %0,%1
++   ldb.x%U1 %0,%1
+    ldb.x%U1 %0,%1"
+-  [(set_attr "type" "unary,unary,load")
+-   (set_attr "iscompact" "true,false,false")])
++  [(set_attr "type" "unary,unary,load,load")
++   (set_attr "iscompact" "true,false,false,false")
++   (set_attr "length" "*,*,*,8")])
+ 
+ 
+ (define_expand "extendqihi2"
+@@ -1548,15 +1559,17 @@
+ )
+ 
+ (define_insn "*extendqisi2_ac"
+-  [(set (match_operand:SI 0 "dest_reg_operand" "=Rcqq,w,r")
+-	(sign_extend:SI (match_operand:QI 1 "nonvol_nonimm_operand" "Rcqq,c,m")))]
++  [(set (match_operand:SI 0 "dest_reg_operand" "=Rcqq,w,r,r")
++	(sign_extend:SI (match_operand:QI 1 "nonvol_nonimm_operand" "Rcqq,c,Uex,m")))]
+   ""
+   "@
+    sexb%? %0,%1%&
+    sexb %0,%1
++   ldb.x%U1 %0,%1
+    ldb.x%U1 %0,%1"
+-  [(set_attr "type" "unary,unary,load")
+-   (set_attr "iscompact" "true,false,false")])
++  [(set_attr "type" "unary,unary,load,load")
++   (set_attr "iscompact" "true,false,false,false")
++   (set_attr "length" "*,*,*,8")])
+ 
+ (define_expand "extendqisi2"
+   [(set (match_operand:SI 0 "dest_reg_operand" "")
+@@ -1566,15 +1579,17 @@
+ )
+ 
+ (define_insn "*extendhisi2_i"
+-  [(set (match_operand:SI 0 "dest_reg_operand" "=Rcqq,w,r")
+-	(sign_extend:SI (match_operand:HI 1 "nonvol_nonimm_operand" "Rcqq,c,m")))]
++  [(set (match_operand:SI 0 "dest_reg_operand" "=Rcqq,w,r,r")
++	(sign_extend:SI (match_operand:HI 1 "nonvol_nonimm_operand" "Rcqq,c,Uex,m")))]
+   ""
+   "@
+    sex%_%? %0,%1%&
+    sex%_ %0,%1
++   ld%_.x%U1%V1 %0,%1
+    ld%_.x%U1%V1 %0,%1"
+-  [(set_attr "type" "unary,unary,load")
+-   (set_attr "iscompact" "true,false,false")])
++  [(set_attr "type" "unary,unary,load,load")
++   (set_attr "iscompact" "true,false,false,false")
++   (set_attr "length" "*,*,4,8")])
+ 
+ (define_expand "extendhisi2"
+   [(set (match_operand:SI 0 "dest_reg_operand" "")
+diff --git a/gcc/config/arc/arc.opt b/gcc/config/arc/arc.opt
+index 45bb6a6167d3..b2c7b3763c1d 100644
+--- a/gcc/config/arc/arc.opt
++++ b/gcc/config/arc/arc.opt
+@@ -469,3 +469,11 @@ Specify thread pointer register number
+ 
+ mtp-regno=none
+ Target RejectNegative Var(arc_tp_regno,-1)
++
++mcmem
++Target Report Var(TARGET_NPS_CMEM) Init(TARGET_NPS_CMEM_DEFAULT)
++Enable use of NPS400 xld/xst extension.
++
++munaligned-access
++Target Report Var(unaligned_access) Init(UNALIGNED_ACCESS_DEFAULT)
++Enable unaligned word and halfword accesses to packed data.
+diff --git a/gcc/config/arc/constraints.md b/gcc/config/arc/constraints.md
+index b6954ad9456a..c2992c9e9473 100644
+--- a/gcc/config/arc/constraints.md
++++ b/gcc/config/arc/constraints.md
+@@ -269,6 +269,13 @@
+   (and (match_code "mem")
+        (match_test "compact_store_memory_operand (op, VOIDmode)")))
+ 
++(define_memory_constraint "Uex"
++  "@internal
++   A valid memory operand for limm-free extend instructions"
++  (and (match_code "mem")
++       (match_test "!cmem_address (XEXP (op, 0), SImode)")
++       (not (match_operand 0 "long_immediate_loadstore_operand"))))
++
+ ; Don't use define_memory_constraint here as the relocation patching
+ ; for small data symbols only works within a ld/st instruction and
+ ; define_memory_constraint may result in the address being calculated
+@@ -303,6 +310,12 @@
+        (match_test "REG_P (XEXP (XEXP (op, 0), 0))")
+        (match_test "REGNO (XEXP (XEXP (op, 0), 0)) == SP_REG")))
+ 
++(define_constraint "Ucm"
++  "@internal
++  cmem access"
++  (and (match_code "mem")
++       (match_test "TARGET_NPS_CMEM && cmem_address (XEXP (op, 0), VOIDmode)")))
++
+ ;; General constraints
+ 
+ (define_constraint "Cbr"
+@@ -430,4 +443,3 @@
+ (define_memory_constraint "ATO"
+   "A memory with only a base register"
+   (match_operand 0 "mem_noofs_operand"))
+-
+diff --git a/gcc/config/arc/predicates.md b/gcc/config/arc/predicates.md
+index 3c657c67f0d3..0d2e217bf9d6 100644
+--- a/gcc/config/arc/predicates.md
++++ b/gcc/config/arc/predicates.md
+@@ -123,6 +123,8 @@
+   int size = GET_MODE_SIZE (GET_MODE (op));
+ 
+   op = XEXP (op, 0);
++  if (TARGET_NPS_CMEM && cmem_address (op, SImode))
++    return 0;
+   switch (GET_CODE (op))
+     {
+     case SYMBOL_REF :
+@@ -819,3 +821,20 @@
+ (define_predicate "double_register_operand"
+   (ior (match_test "even_register_operand (op, mode)")
+        (match_test "arc_double_register_operand (op, mode)")))
++
++(define_predicate "cmem_address_0"
++  (and (match_code "symbol_ref")
++       (match_test "SYMBOL_REF_FLAGS (op) & SYMBOL_FLAG_CMEM")))
++
++(define_predicate "cmem_address_1"
++  (and (match_code "plus")
++       (match_test "cmem_address_0 (XEXP (op, 0), SImode)")))
++
++(define_predicate "cmem_address_2"
++  (and (match_code "const")
++       (match_test "cmem_address_1 (XEXP (op, 0), SImode)")))
++
++(define_predicate "cmem_address"
++  (ior (match_operand:SI 0 "cmem_address_0")
++       (match_operand:SI 0 "cmem_address_1")
++       (match_operand:SI 0 "cmem_address_2")))
+diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog
+index d3c6533df2f2..63a13b84ee10 100644
+--- a/gcc/testsuite/ChangeLog
++++ b/gcc/testsuite/ChangeLog
+@@ -1,3 +1,16 @@
++2016-04-28  Joern Rennecke  <joern.rennecke at embecosm.com>
++	    Andrew Burgess  <andrew.burgess at embecosm.com>
++
++	* gcc.target/arc/cmem-1.c: New file.
++	* gcc.target/arc/cmem-2.c: New file.
++	* gcc.target/arc/cmem-3.c: New file.
++	* gcc.target/arc/cmem-4.c: New file.
++	* gcc.target/arc/cmem-5.c: New file.
++	* gcc.target/arc/cmem-6.c: New file.
++	* gcc.target/arc/cmem-7.c: New file.
++	* gcc.target/arc/cmem-ld.inc: New file.
++	* gcc.target/arc/cmem-st.inc: New file.
++
+ 2016-12-21  Release Manager
+ 
+ 	* GCC 6.3.0 released.
+diff --git a/gcc/testsuite/gcc.target/arc/cmem-1.c b/gcc/testsuite/gcc.target/arc/cmem-1.c
+new file mode 100644
+index 000000000000..7f36afbfa7d8
+--- /dev/null
++++ b/gcc/testsuite/gcc.target/arc/cmem-1.c
+@@ -0,0 +1,10 @@
++/* { dg-do compile } */
++/* { dg-options "-mcpu=nps400 -mcmem" } */
++
++#define CMEM_SECTION_ATTR __attribute__ ((section (".cmem")));
++
++#include "cmem-st.inc"
++
++/* { dg-final { scan-assembler "xst " } } */
++/* { dg-final { scan-assembler "xstw " } } */
++/* { dg-final { scan-assembler "xstb " } } */
+diff --git a/gcc/testsuite/gcc.target/arc/cmem-2.c b/gcc/testsuite/gcc.target/arc/cmem-2.c
+new file mode 100644
+index 000000000000..a3d7c130b5e8
+--- /dev/null
++++ b/gcc/testsuite/gcc.target/arc/cmem-2.c
+@@ -0,0 +1,10 @@
++/* { dg-do compile } */
++/* { dg-options "-mcpu=nps400 -mcmem" } */
++
++#define CMEM_SECTION_ATTR __attribute__ ((section (".cmem")));
++
++#include "cmem-ld.inc"
++
++/* { dg-final { scan-assembler "xld " } } */
++/* { dg-final { scan-assembler "xldw " } } */
++/* { dg-final { scan-assembler "xldb " } } */
+diff --git a/gcc/testsuite/gcc.target/arc/cmem-3.c b/gcc/testsuite/gcc.target/arc/cmem-3.c
+new file mode 100644
+index 000000000000..dee73b5c5d30
+--- /dev/null
++++ b/gcc/testsuite/gcc.target/arc/cmem-3.c
+@@ -0,0 +1,10 @@
++/* { dg-do compile } */
++/* { dg-options "-mcpu=nps400 -mcmem" } */
++
++#define CMEM_SECTION_ATTR __attribute__ ((section (".cmem_private")));
++
++#include "cmem-st.inc"
++
++/* { dg-final { scan-assembler "xst " } } */
++/* { dg-final { scan-assembler "xstw " } } */
++/* { dg-final { scan-assembler "xstb " } } */
+diff --git a/gcc/testsuite/gcc.target/arc/cmem-4.c b/gcc/testsuite/gcc.target/arc/cmem-4.c
+new file mode 100644
+index 000000000000..1da6bce77c48
+--- /dev/null
++++ b/gcc/testsuite/gcc.target/arc/cmem-4.c
+@@ -0,0 +1,10 @@
++/* { dg-do compile } */
++/* { dg-options "-mcpu=nps400 -mcmem" } */
++
++#define CMEM_SECTION_ATTR __attribute__ ((section (".cmem_private")));
++
++#include "cmem-ld.inc"
++
++/* { dg-final { scan-assembler "xld " } } */
++/* { dg-final { scan-assembler "xldw " } } */
++/* { dg-final { scan-assembler "xldb " } } */
+diff --git a/gcc/testsuite/gcc.target/arc/cmem-5.c b/gcc/testsuite/gcc.target/arc/cmem-5.c
+new file mode 100644
+index 000000000000..ad6904f73605
+--- /dev/null
++++ b/gcc/testsuite/gcc.target/arc/cmem-5.c
+@@ -0,0 +1,10 @@
++/* { dg-do compile } */
++/* { dg-options "-mcpu=nps400 -mcmem" } */
++
++#define CMEM_SECTION_ATTR __attribute__ ((section (".cmem_shared")));
++
++#include "cmem-st.inc"
++
++/* { dg-final { scan-assembler "xst " } } */
++/* { dg-final { scan-assembler "xstw " } } */
++/* { dg-final { scan-assembler "xstb " } } */
+diff --git a/gcc/testsuite/gcc.target/arc/cmem-6.c b/gcc/testsuite/gcc.target/arc/cmem-6.c
+new file mode 100644
+index 000000000000..24bc39bfd07c
+--- /dev/null
++++ b/gcc/testsuite/gcc.target/arc/cmem-6.c
+@@ -0,0 +1,10 @@
++/* { dg-do compile } */
++/* { dg-options "-mcpu=nps400 -mcmem" } */
++
++#define CMEM_SECTION_ATTR __attribute__ ((section (".cmem_shared")));
++
++#include "cmem-ld.inc"
++
++/* { dg-final { scan-assembler "xld " } } */
++/* { dg-final { scan-assembler "xldw " } } */
++/* { dg-final { scan-assembler "xldb " } } */
+diff --git a/gcc/testsuite/gcc.target/arc/cmem-7.c b/gcc/testsuite/gcc.target/arc/cmem-7.c
+new file mode 100644
+index 000000000000..72ee7bdffafb
+--- /dev/null
++++ b/gcc/testsuite/gcc.target/arc/cmem-7.c
+@@ -0,0 +1,26 @@
++/* { dg-do compile } */
++/* { dg-options "-mcpu=nps400 -mcmem" } */
++
++struct some_struct
++{
++  unsigned char a;
++};
++
++unsigned char other_func (unsigned char);
++
++unsigned char
++some_function ()
++{
++  static struct some_struct ss __attribute__ ((section (".cmem")));
++  static struct some_struct tt;
++
++  ss.a = other_func (ss.a);
++  tt.a = other_func (tt.a);
++
++  return 0;
++}
++
++/* { dg-final { scan-assembler "xldb \[^\n\]*@ss" } } */
++/* { dg-final { scan-assembler "xstb \[^\n\]*@ss" } } */
++/* { dg-final { scan-assembler-not "xldb \[^\n\]*@tt" } } */
++/* { dg-final { scan-assembler-not "xstb \[^\n\]*@tt" } } */
+diff --git a/gcc/testsuite/gcc.target/arc/cmem-ld.inc b/gcc/testsuite/gcc.target/arc/cmem-ld.inc
+new file mode 100644
+index 000000000000..7b51bb39a174
+--- /dev/null
++++ b/gcc/testsuite/gcc.target/arc/cmem-ld.inc
+@@ -0,0 +1,16 @@
++
++struct foo_type
++{
++  unsigned int a;
++  unsigned short b;
++  unsigned char c;
++};
++
++struct foo_type foo __attribute__ ((section (".cmem")));
++
++unsigned int
++f ()
++{
++  unsigned int tmp = foo.a + foo.b + foo.c;
++  return tmp;
++}
+diff --git a/gcc/testsuite/gcc.target/arc/cmem-st.inc b/gcc/testsuite/gcc.target/arc/cmem-st.inc
+new file mode 100644
+index 000000000000..30aeace6609e
+--- /dev/null
++++ b/gcc/testsuite/gcc.target/arc/cmem-st.inc
+@@ -0,0 +1,18 @@
++
++struct foo_type
++{
++  unsigned int a;
++  unsigned short b;
++  unsigned char c;
++};
++
++struct foo_type foo CMEM_SECTION_ATTR
++
++int
++f ()
++{
++  foo.a = 3;
++  foo.b = 2;
++  foo.c = 1;
++  return 0;
++}
+-- 
+2.7.4
+
diff --git a/toolchain/gcc/patches/6.3.0/0010-2016-04-28-Joern-Rennecke-joern.rennecke-embecosm.co.patch b/toolchain/gcc/patches/6.3.0/0010-2016-04-28-Joern-Rennecke-joern.rennecke-embecosm.co.patch
new file mode 100644
index 0000000..66be802
--- /dev/null
+++ b/toolchain/gcc/patches/6.3.0/0010-2016-04-28-Joern-Rennecke-joern.rennecke-embecosm.co.patch
@@ -0,0 +1,1059 @@
+From e4b82df8479716978403370dfdde0a4a241306ab Mon Sep 17 00:00:00 2001
+From: amylaar <amylaar at 138bc75d-0d04-0410-961f-82ee72b054a4>
+Date: Thu, 28 Apr 2016 18:48:43 +0000
+Subject: [PATCH 10/89] 2016-04-28  Joern Rennecke 
+ <joern.rennecke at embecosm.com>             Andrew Burgess 
+ <andrew.burgess at embecosm.com> gcc:         * config/arc/arc.h
+ (SYMBOL_FLAG_CMEM): Define.         (TARGET_NPS_CMEM_DEFAULT): Provide
+ default definition.         * config/arc/arc.c (arc_address_cost): Return 0
+ for cmem_address.         (arc_encode_section_info): Set SYMBOL_FLAG_CMEM
+ where indicated.         * config/arc/arc.opt (mcmem): New option.         *
+ config/arc/arc.md (*extendqihi2_i): Add r/Uex alternative,         supply
+ length for r/m alternative.         (*extendqisi2_ac): Likewise.        
+ (*extendhisi2_i): Add r/Uex alternative, supply length for r/m and        
+ r/Uex alternative.         (movqi_insn): Add r/Ucm and Ucm/?Rac alternatives.
+         (movhi_insn): Likewise.         (movsi_insn): Add r/Ucm,Ucm/w
+ alternatives.         (*zero_extendqihi2_i): Add r/Ucm alternative.        
+ (*zero_extendqisi2_ac): Likewise.         (*zero_extendhisi2_i): Likewise.   
+      * config/arc/constraints.md (Uex): New memory constraint.         (Ucm):
+ New define_constraint.         * config/arc/predicates.md
+ (long_immediate_loadstore_operand):         Return 0 for MEM with
+ cmem_address address.         (cmem_address_0): New predicates.        
+ (cmem_address_1): Likewise.         (cmem_address_2): Likewise.        
+ (cmem_address): Likewise. gcc/testsuite:         * gcc.target/arc/cmem-1.c:
+ New file.         * gcc.target/arc/cmem-2.c: New file.         *
+ gcc.target/arc/cmem-3.c: New file.         * gcc.target/arc/cmem-4.c: New
+ file.         * gcc.target/arc/cmem-5.c: New file.         *
+ gcc.target/arc/cmem-6.c: New file.         * gcc.target/arc/cmem-7.c: New
+ file.         * gcc.target/arc/cmem-ld.inc: New file.         *
+ gcc.target/arc/cmem-st.inc: New file.
+
+git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@235595 138bc75d-0d04-0410-961f-82ee72b054a4
+---
+ gcc/ChangeLog                             |  42 ++++
+ gcc/config/arc/arc.c                      |  33 ++-
+ gcc/config/arc/arc.h                      |   9 +
+ gcc/config/arc/arc.md                     | 382 ++++++++++++++++++++++++++----
+ gcc/config/arc/arc.opt                    |   4 +
+ gcc/config/arc/constraints.md             |  58 ++++-
+ gcc/testsuite/ChangeLog                   |  16 ++
+ gcc/testsuite/gcc.target/arc/extzv-1.c    |  11 +
+ gcc/testsuite/gcc.target/arc/insv-1.c     |  21 ++
+ gcc/testsuite/gcc.target/arc/insv-2.c     |  18 ++
+ gcc/testsuite/gcc.target/arc/movb-1.c     |  13 +
+ gcc/testsuite/gcc.target/arc/movb-2.c     |  13 +
+ gcc/testsuite/gcc.target/arc/movb-3.c     |  13 +
+ gcc/testsuite/gcc.target/arc/movb-4.c     |  13 +
+ gcc/testsuite/gcc.target/arc/movb-5.c     |  13 +
+ gcc/testsuite/gcc.target/arc/movb_cl-1.c  |   9 +
+ gcc/testsuite/gcc.target/arc/movb_cl-2.c  |  11 +
+ gcc/testsuite/gcc.target/arc/movbi_cl-1.c |   9 +
+ gcc/testsuite/gcc.target/arc/movl-1.c     |  17 ++
+ 19 files changed, 648 insertions(+), 57 deletions(-)
+ create mode 100644 gcc/testsuite/gcc.target/arc/extzv-1.c
+ create mode 100644 gcc/testsuite/gcc.target/arc/insv-1.c
+ create mode 100644 gcc/testsuite/gcc.target/arc/insv-2.c
+ create mode 100644 gcc/testsuite/gcc.target/arc/movb-1.c
+ create mode 100644 gcc/testsuite/gcc.target/arc/movb-2.c
+ create mode 100644 gcc/testsuite/gcc.target/arc/movb-3.c
+ create mode 100644 gcc/testsuite/gcc.target/arc/movb-4.c
+ create mode 100644 gcc/testsuite/gcc.target/arc/movb-5.c
+ create mode 100644 gcc/testsuite/gcc.target/arc/movb_cl-1.c
+ create mode 100644 gcc/testsuite/gcc.target/arc/movb_cl-2.c
+ create mode 100644 gcc/testsuite/gcc.target/arc/movbi_cl-1.c
+ create mode 100644 gcc/testsuite/gcc.target/arc/movl-1.c
+
+diff --git a/gcc/ChangeLog b/gcc/ChangeLog
+index f0d877721dd3..5d03f67fa40b 100644
+--- a/gcc/ChangeLog
++++ b/gcc/ChangeLog
+@@ -1,6 +1,48 @@
+ 2016-04-28  Joern Rennecke  <joern.rennecke at embecosm.com>
+ 	    Andrew Burgess  <andrew.burgess at embecosm.com>
+ 
++	* config/arc/arc.c (arc_conditional_register_usage): Take
++	TARGET_RRQ_CLASS into account.
++	(arc_print_operand): Support printing 'p' and 's' operands.
++	* config/arc/arc.h (TARGET_NPS_BITOPS_DEFAULT): Provide default
++	as 0.
++	(TARGET_RRQ_CLASS): Define.
++	(IS_POWEROF2_OR_0_P): Define.
++	* config/arc/arc.md (*movsi_insn): Add w/Clo, w/Chi, and w/Cbi
++	alternatives.
++	(*tst_movb): New define_insn.
++	(*tst): Avoid recognition if it could prevent '*tst_movb'
++	combination; replace c/CnL with c/Chs alternative.
++	(*tst_bitfield_tst): New define_insn.
++	(*tst_bitfield_asr): New define_insn.
++	(*tst_bitfield): New define_insn.
++	(andsi3_i): Add Rrq variant.
++	(extzv): New define_expand.
++	(insv): New define_expand.
++	(*insv_i): New define_insn.
++	(*movb): New define_insn.
++	(*movb_signed): New define_insn.
++	(*movb_high): New define_insn.
++	(*movb_high_signed): New define_insn.
++	(*movb_high_signed + 1): New define_split pattern.
++	(*mrgb): New define_insn.
++	(*mrgb + 1): New define_peephole2 pattern.
++	(*mrgb + 2): New define_peephole2 pattern.
++	* config/arc/arc.opt (mbitops): New option for nps400, uses
++	TARGET_NPS_BITOPS_DEFAULT.
++	* config/arc/constraints.md (q): Make register class conditional.
++	(Rrq): New register constraint.
++	(Chs): New constraint.
++	(Clo): New constraint.
++	(Chi): New constraint.
++	(Cbf): New constraint.
++	(Cbn): New constraint.
++	(C18): New constraint.
++	(Cbi): New constraint.
++
++2016-04-28  Joern Rennecke  <joern.rennecke at embecosm.com>
++	    Andrew Burgess  <andrew.burgess at embecosm.com>
++
+ 	* config/arc/constraints.md (Usd): Convert to define_constraint.
+ 	(Us<): Likewise.
+ 	(Us>): Likewise.
+diff --git a/gcc/config/arc/arc.c b/gcc/config/arc/arc.c
+index ca9d31ceee95..b7dfab1e0d86 100644
+--- a/gcc/config/arc/arc.c
++++ b/gcc/config/arc/arc.c
+@@ -1430,7 +1430,8 @@ arc_conditional_register_usage (void)
+     {
+       if (i < 29)
+ 	{
+-	  if (TARGET_Q_CLASS && ((i <= 3) || ((i >= 12) && (i <= 15))))
++	  if ((TARGET_Q_CLASS || TARGET_RRQ_CLASS)
++	      && ((i <= 3) || ((i >= 12) && (i <= 15))))
+ 	    arc_regno_reg_class[i] = ARCOMPACT16_REGS;
+ 	  else
+ 	    arc_regno_reg_class[i] = GENERAL_REGS;
+@@ -1447,12 +1448,12 @@ arc_conditional_register_usage (void)
+ 	arc_regno_reg_class[i] = NO_REGS;
+     }
+ 
+-  /* ARCOMPACT16_REGS is empty, if TARGET_Q_CLASS has not been activated.  */
++  /* ARCOMPACT16_REGS is empty, if TARGET_Q_CLASS / TARGET_RRQ_CLASS
++     has not been activated.  */
++  if (!TARGET_Q_CLASS && !TARGET_RRQ_CLASS)
++    CLEAR_HARD_REG_SET(reg_class_contents [ARCOMPACT16_REGS]);
+   if (!TARGET_Q_CLASS)
+-    {
+-      CLEAR_HARD_REG_SET(reg_class_contents [ARCOMPACT16_REGS]);
+-      CLEAR_HARD_REG_SET(reg_class_contents [AC16_BASE_REGS]);
+-    }
++    CLEAR_HARD_REG_SET(reg_class_contents [AC16_BASE_REGS]);
+ 
+   gcc_assert (FIRST_PSEUDO_REGISTER >= 144);
+ 
+@@ -2994,6 +2995,8 @@ static int output_scaled = 0;
+     'Z': log2(x+1)-1
+     'z': log2
+     'M': log2(~x)
++    'p': bit Position of lsb
++    's': size of bit field
+     '#': condbranch delay slot suffix
+     '*': jump delay slot suffix
+     '?' : nonjump-insn suffix for conditional execution or short instruction
+@@ -3044,6 +3047,24 @@ arc_print_operand (FILE *file, rtx x, int code)
+ 
+       return;
+ 
++    case 'p':
++      if (GET_CODE (x) == CONST_INT)
++	fprintf (file, "%d", exact_log2 (INTVAL (x) & -INTVAL (x)));
++      else
++	output_operand_lossage ("invalid operand to %%p code");
++      return;
++
++    case 's':
++      if (GET_CODE (x) == CONST_INT)
++	{
++	  HOST_WIDE_INT i = INTVAL (x);
++	  HOST_WIDE_INT s = exact_log2 (i & -i);
++	  fprintf (file, "%d", exact_log2 (((0xffffffffUL & i) >> s) + 1));
++	}
++      else
++	output_operand_lossage ("invalid operand to %%s code");
++      return;
++
+     case '#' :
+       /* Conditional branches depending on condition codes.
+ 	 Note that this is only for branches that were known to depend on
+diff --git a/gcc/config/arc/arc.h b/gcc/config/arc/arc.h
+index a17d41092507..4235eabc96d3 100644
+--- a/gcc/config/arc/arc.h
++++ b/gcc/config/arc/arc.h
+@@ -326,10 +326,18 @@ along with GCC; see the file COPYING3.  If not see
+ #define UNALIGNED_ACCESS_DEFAULT 0
+ #endif
+ 
++#ifndef TARGET_NPS_BITOPS_DEFAULT
++#define TARGET_NPS_BITOPS_DEFAULT 0
++#endif
++
+ #ifndef TARGET_NPS_CMEM_DEFAULT
+ #define TARGET_NPS_CMEM_DEFAULT 0
+ #endif
+ 
++/* Enable the RRQ instruction alternatives.  */
++
++#define TARGET_RRQ_CLASS TARGET_NPS_BITOPS
++
+ /* Target machine storage layout.  */
+ 
+ /* We want zero_extract to mean the same
+@@ -1033,6 +1041,7 @@ extern int arc_initial_elimination_offset(int from, int to);
+ 
+ /* Is the argument a const_int rtx, containing an exact power of 2 */
+ #define  IS_POWEROF2_P(X) (! ( (X) & ((X) - 1)) && (X))
++#define  IS_POWEROF2_OR_0_P(X) (! ( (X) & ((X) - 1)))
+ 
+ /* The macros REG_OK_FOR..._P assume that the arg is a REG rtx
+    and check its validity for a certain class.
+diff --git a/gcc/config/arc/arc.md b/gcc/config/arc/arc.md
+index 93a2cad7dfa6..7c30eb46e072 100644
+--- a/gcc/config/arc/arc.md
++++ b/gcc/config/arc/arc.md
+@@ -700,8 +700,8 @@
+ ; insns it should lengthen the return insn.
+ ; N.B. operand 1 of alternative 7 expands into pcl,symbol at gotpc .
+ (define_insn "*movsi_insn"
+-  [(set (match_operand:SI 0 "move_dest_operand" "=Rcq,Rcq#q,w, w,w,  w,???w, ?w,  w,Rcq#q, w,Rcq,  S,Us<,RcqRck,!*x,r,r,Ucm,m,???m,VUsc")
+-	(match_operand:SI 1 "move_src_operand"  " cL,cP,Rcq#q,cL,I,Crr,?Rac,Cpc,Clb,?Cal,?Cal,T,Rcq,RcqRck,Us>,Usd,Ucm,m,w,c,?Rac,C32"))]
++  [(set (match_operand:SI 0 "move_dest_operand" "=Rcq,Rcq#q,w,w,w,w,w,w,w,???w,?w,w,Rcq#q,w,Rcq,S,Us<,RcqRck,!*x,r,r,Ucm,m,???m,VUsc")
++	(match_operand:SI 1 "move_src_operand"  "cL,cP,Rcq#q,cL,I,Crr,Clo,Chi,Cbi,?Rac,Cpc,Clb,?Cal,?Cal,T,Rcq,RcqRck,Us>,Usd,Ucm,m,w,c,?Rac,C32"))]
+   "register_operand (operands[0], SImode)
+    || register_operand (operands[1], SImode)
+    || (CONSTANT_P (operands[1])
+@@ -716,29 +716,32 @@
+    mov%? %0,%1		;3
+    mov%? %0,%1		;4
+    ror %0,((%1*2+1) & 0x3f) ;5
+-   mov%? %0,%1		;6
+-   add %0,%S1		;7
++   movl.cl %0,%1       ;6
++   movh.cl %0,%L1>>16  ;7
++   * return INTVAL (operands[1]) & 0xffffff ? \"movbi.cl %0,%1 >> %p1,%p1,8;8\" : \"movbi.cl %0,%L1 >> 24,24,8;9\";
++   mov%? %0,%1		;9
++   add %0,%S1		;10
+    * return arc_get_unalign () ? \"add %0,pcl,%1-.+2\" : \"add %0,pcl,%1-.\";
+-   mov%? %0,%S1%&	;9
+-   mov%? %0,%S1		;10
+-   ld%? %0,%1%&		;11
+-   st%? %1,%0%&		;12
++   mov%? %0,%S1%&	;12
++   mov%? %0,%S1		;13
++   ld%? %0,%1%&		;14
++   st%? %1,%0%&		;15
+    * return arc_short_long (insn, \"push%? %1%&\", \"st%U0 %1,%0%&\");
+    * return arc_short_long (insn, \"pop%? %0%&\",  \"ld%U1 %0,%1%&\");
+-   ld%? %0,%1%&		;15
+-   xld%U1 %0,%1         ;16
+-   ld%U1%V1 %0,%1	;17
+-   xst%U0 %1,%0         ;18
+-   st%U0%V0 %1,%0       ;19
+-   st%U0%V0 %1,%0       ;20
+-   st%U0%V0 %S1,%0      ;21"
+-  [(set_attr "type" "move,move,move,move,move,two_cycle_core,move,binary,binary,move,move,load,store,store,load,load,load,load,store,store,store,store")
+-   (set_attr "iscompact" "maybe,maybe,maybe,false,false,false,false,false,false,maybe_limm,false,true,true,true,true,true,false,false,false,false,false,false")
++   ld%? %0,%1%&		;18
++   xld%U1 %0,%1                ;19
++   ld%U1%V1 %0,%1	;20
++   xst%U0 %1,%0                ;21
++   st%U0%V0 %1,%0       ;22
++   st%U0%V0 %1,%0       ;23
++   st%U0%V0 %S1,%0      ;24"
++  [(set_attr "type" "move,move,move,move,move,two_cycle_core,shift,shift,shift,move,binary,binary,move,move,load,store,store,load,load,load,load,store,store,store,store")
++   (set_attr "iscompact" "maybe,maybe,maybe,false,false,false,false,false,false,false,false,false,maybe_limm,false,true,true,true,true,true,false,false,false,false,false,false")
+    ; Use default length for iscompact to allow for COND_EXEC.  But set length
+    ; of Crr to 4.
+-   (set_attr "length" "*,*,*,4,4,4,4,8,8,*,8,*,*,*,*,*,4,*,4,*,*,8")
+-   (set_attr "predicable" "yes,no,yes,yes,no,no,yes,no,no,yes,yes,no,no,no,no,no,no,no,no,no,no,no")
+-   (set_attr "cpu_facility" "*,*,av1,*,*,*,*,*,*,*,*,*,*,*,*,*,*,*,*,*,*,*")])
++   (set_attr "length" "*,*,*,4,4,4,4,4,4,4,8,8,*,8,*,*,*,*,*,4,*,4,*,*,8")
++   (set_attr "predicable" "yes,no,yes,yes,no,no,no,no,no,yes,no,no,yes,yes,no,no,no,no,no,no,no,no,no,no,no")
++   (set_attr "cpu_facility" "*,*,av1,*,*,*,*,*,*,*,*,*,*,*,*,*,*,*,*,*,*,*,*,*,*")])
+ 
+ ;; Sometimes generated by the epilogue code.  We don't want to
+ ;; recognize these addresses in general, because the limm is costly,
+@@ -809,6 +812,24 @@
+    (set_attr "cond" "set_zn")
+    (set_attr "length" "4")])
+ 
++; reload is too stingy with reloads for Rrq/Cbf/Rrq when it sees
++; a c/???Cal/X alternative, so we say it's c/???Cal/c instead,
++; even if we don't need the clobber.
++(define_insn_and_split "*tst_movb"
++  [(set
++     (match_operand 0 "cc_register" "")
++     (match_operator 4 "zn_compare_operator"
++       [(and:SI
++	  (match_operand:SI 1 "register_operand"  "%Rcq,Rcq, c,  c,  c,  c,Rrq,  3,  c")
++	  (match_operand:SI 2 "nonmemory_operand"  "Rcq,C0p,cI,C1p,Ccp,Chs,Cbf,Cbf,???Cal"))
++	(const_int 0)]))
++   (clobber (match_scratch:SI 3 "=X,X,X,X,X,X,Rrq,Rrq,c"))]
++  "TARGET_NPS_BITOPS"
++  "movb.f.cl %3,%1,%p2,%p2,%s2"
++  "reload_completed
++   && (extract_constrain_insn_cached (insn), (which_alternative & ~1) != 6)"
++  [(set (match_dup 0) (match_dup 4))])
++
+ (define_insn "*tst"
+   [(set
+      (match_operand 0 "cc_register" "")
+@@ -817,12 +838,14 @@
+ 	  (match_operand:SI 1 "register_operand"
+ 	   "%Rcq,Rcq, c, c, c,  c,  c,  c")
+ 	  (match_operand:SI 2 "nonmemory_operand"
+-	   " Rcq,C0p,cI,cL,C1p,Ccp,CnL,Cal"))
++	   " Rcq,C0p,cI,cL,C1p,Ccp,Chs,Cal"))
+ 	(const_int 0)]))]
+-  "(register_operand (operands[1], SImode)
+-    && nonmemory_operand (operands[2], SImode))
+-   || (memory_operand (operands[1], SImode)
+-       && satisfies_constraint_Cux (operands[2]))"
++  "reload_completed
++   || !satisfies_constraint_Cbf (operands[2])
++   || satisfies_constraint_C0p (operands[2])
++   || satisfies_constraint_I (operands[2])
++   || satisfies_constraint_C1p (operands[2])
++   || satisfies_constraint_Chs (operands[2])"
+   "*
+     switch (which_alternative)
+     {
+@@ -835,17 +858,79 @@
+     case 5:
+       return \"bclr%?.f 0,%1,%M2%&\";
+     case 6:
+-      return \"bic%?.f 0,%1,%n2-1\";
++      return \"asr.f 0,%1,%p2\";
+     default:
+       gcc_unreachable ();
+     }
+   "
+   [(set_attr "iscompact" "maybe,maybe,false,false,false,false,false,false")
+-   (set_attr "type" "compare")
++   (set_attr "type" "compare,compare,compare,compare,compare,compare,shift,compare")
+    (set_attr "length" "*,*,4,4,4,4,4,8")
+    (set_attr "predicable" "no,yes,no,yes,no,no,no,yes")
+    (set_attr "cond" "set_zn")])
+ 
++; ??? Sometimes, if an AND with a constant can be expressed as a zero_extract,
++; combine will do that and not try the AND.
++
++; It would take 66 constraint combinations to describe the zero_extract
++; constants that are covered by the 12-bit signed constant for tst
++; (excluding the ones that are better done by mov or btst).
++; so we rather use an extra pattern for tst;
++; since this is about constants, reload shouldn't care.
++(define_insn "*tst_bitfield_tst"
++  [(set (match_operand:CC_ZN 0 "cc_set_register" "")
++	(match_operator 4 "zn_compare_operator"
++	  [(zero_extract:SI
++	     (match_operand:SI 1 "register_operand"  "c")
++	     (match_operand:SI 2 "const_int_operand" "n")
++	     (match_operand:SI 3 "const_int_operand" "n"))
++	   (const_int 0)]))]
++  "INTVAL (operands[2]) > 1
++   && (INTVAL (operands[3]) + INTVAL (operands[2]) <= 11
++       || (INTVAL (operands[3]) <= 11
++	   && INTVAL (operands[3]) + INTVAL (operands[2]) == 32))"
++  "tst %1,(1<<%2)-1<<%3"
++  [(set_attr "type" "compare")
++   (set_attr "cond" "set_zn")
++   (set_attr "length" "4")])
++
++; Likewise for asr.f.
++(define_insn "*tst_bitfield_asr"
++  [(set (match_operand:CC_ZN 0 "cc_set_register" "")
++	(match_operator 4 "zn_compare_operator"
++	  [(zero_extract:SI
++	     (match_operand:SI 1 "register_operand"  "c")
++	     (match_operand:SI 2 "const_int_operand" "n")
++	     (match_operand:SI 3 "const_int_operand" "n"))
++	   (const_int 0)]))]
++  "INTVAL (operands[2]) > 1
++   && INTVAL (operands[3]) + INTVAL (operands[2]) == 32"
++  "asr.f 0,%1,%3"
++  [(set_attr "type" "shift")
++   (set_attr "cond" "set_zn")
++   (set_attr "length" "4")])
++
++(define_insn "*tst_bitfield"
++  [(set (match_operand:CC_ZN 0 "cc_set_register" "")
++	(match_operator 5 "zn_compare_operator"
++	  [(zero_extract:SI
++	     (match_operand:SI 1 "register_operand" "%Rcqq,c,  c,Rrq,c")
++	     (match_operand:SI 2 "const_int_operand"    "N,N,  n,Cbn,n")
++	     (match_operand:SI 3 "const_int_operand"    "n,n,C_0,Cbn,n"))
++	   (const_int 0)]))
++   (clobber (match_scratch:SI 4 "=X,X,X,Rrq,X"))]
++  ""
++  "@
++   btst%? %1,%3
++   btst %1,%3
++   bmsk.f 0,%1,%2-1
++   movb.f.cl %4,%1,%3,%3,%2
++   and.f 0,%1,((1<<%2)-1)<<%3"
++  [(set_attr "iscompact" "maybe,false,false,false,false")
++   (set_attr "type" "compare,compare,compare,shift,compare")
++   (set_attr "cond" "set_zn")
++   (set_attr "length" "*,4,4,4,8")])
++
+ (define_insn "*commutative_binary_comparison"
+   [(set (match_operand:CC_ZN 0 "cc_set_register" "")
+ 	(match_operator:CC_ZN 5 "zn_compare_operator"
+@@ -2956,30 +3041,40 @@
+      operands[1] = arc_rewrite_small_data (operands[1]);")
+ 
+ (define_insn "andsi3_i"
+-  [(set (match_operand:SI 0 "dest_reg_operand"          "=Rcqq,Rcq,Rcqq,Rcqq,Rcqq,Rcw,Rcw,Rcw,Rcw,Rcw,Rcw,  w,  w,  w,  w,w,Rcw,  w,  W")
+-	(and:SI (match_operand:SI 1 "nonimmediate_operand" "%0,Rcq,   0,   0,Rcqq,  0,  c,  0,  0,  0,  0,  c,  c,  c,  c,0,  0,  c,  o")
+-		(match_operand:SI 2 "nonmemory_operand" " Rcqq,  0, C1p, Ccp, Cux, cL,  0,C1p,Ccp,CnL,  I, Lc,C1p,Ccp,CnL,I,Cal,Cal,Cux")))]
++  [(set (match_operand:SI 0 "dest_reg_operand" "=Rcqq,Rcq,Rcqq,Rcqq,Rcqq,Rcw,Rcw,Rcw,Rcw,Rcw,Rcw,w,w,w,w,Rrq,w,Rcw,w,W")
++	(and:SI (match_operand:SI 1 "nonimmediate_operand" "%0,Rcq,0,0,Rcqq,0,c,0,0,0,0,c,c,c,c,Rrq,0,0,c,o")
++		(match_operand:SI 2 "nonmemory_operand" "Rcqq,0,C1p,Ccp,Cux,cL,0,C1p,Ccp,CnL,I,Lc,C1p,Ccp,CnL,Cbf,I,Cal,Cal,Cux")))]
+   "(register_operand (operands[1], SImode)
+     && nonmemory_operand (operands[2], SImode))
+    || (memory_operand (operands[1], SImode)
+        && satisfies_constraint_Cux (operands[2]))"
+-  "*
+ {
+   switch (which_alternative)
+     {
+-    case 0: case 5: case 10: case 11: case 15: case 16: case 17:
+-      return \"and%? %0,%1,%2%&\";
++    case 0: case 5: case 10: case 11: case 16: case 17: case 18:
++      return "and%? %0,%1,%2%&";
+     case 1: case 6:
+-      return \"and%? %0,%2,%1%&\";
++      return "and%? %0,%2,%1%&";
+     case 2: case 7: case 12:
+-      return \"bmsk%? %0,%1,%Z2%&\";
++      return "bmsk%? %0,%1,%Z2%&";
+     case 3: case 8: case 13:
+-      return \"bclr%? %0,%1,%M2%&\";
++      return "bclr%? %0,%1,%M2%&";
+     case 4:
+       return (INTVAL (operands[2]) == 0xff
+-	      ? \"extb%? %0,%1%&\" : \"ext%_%? %0,%1%&\");
++	      ? "extb%? %0,%1%&" : "ext%_%? %0,%1%&");
+     case 9: case 14: return \"bic%? %0,%1,%n2-1\";
+-    case 18:
++    case 15:
++      return "movb.cl %0,%1,%p2,%p2,%s2";
++
++    case 19:
++      const char *tmpl;
++
++      if (satisfies_constraint_Ucm (operands[1]))
++	tmpl = (INTVAL (operands[2]) == 0xff
++		? "xldb%U1 %0,%1" : "xld%_%U1 %0,%1");
++      else
++	tmpl = INTVAL (operands[2]) == 0xff ? "ldb %0,%1" : "ld%_ %0,%1";
++
+       if (TARGET_BIG_ENDIAN)
+ 	{
+ 	  rtx xop[2];
+@@ -2987,21 +3082,19 @@
+ 	  xop[0] = operands[0];
+ 	  xop[1] = adjust_address (operands[1], QImode,
+ 				   INTVAL (operands[2]) == 0xff ? 3 : 2);
+-	  output_asm_insn (INTVAL (operands[2]) == 0xff
+-			   ? \"ldb %0,%1\" : \"ld%_ %0,%1\",
+-			   xop);
+-	  return \"\";
++	  output_asm_insn (tmpl, xop);
++	  return "";
+ 	}
+-      return INTVAL (operands[2]) == 0xff ? \"ldb %0,%1\" : \"ld%_ %0,%1\";
++      return tmpl;
+     default:
+       gcc_unreachable ();
+     }
+-}"
+-  [(set_attr "iscompact" "maybe,maybe,maybe,maybe,true,false,false,false,false,false,false,false,false,false,false,false,false,false,false")
+-   (set_attr "type" "binary,binary,binary,binary,binary,binary,binary,binary,binary,binary,binary,binary,binary,binary,binary,binary,binary,binary,load")
+-   (set_attr "length" "*,*,*,*,*,4,4,4,4,4,4,4,4,4,4,4,8,8,*")
+-   (set_attr "predicable" "no,no,no,no,no,yes,yes,yes,yes,yes,no,no,no,no,no,no,yes,no,no")
+-   (set_attr "cond" "canuse,canuse,canuse,canuse,nocond,canuse,canuse,canuse,canuse,canuse,canuse_limm,nocond,nocond,nocond,nocond,canuse_limm,canuse,nocond,nocond")])
++}
++  [(set_attr "iscompact" "maybe,maybe,maybe,maybe,true,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false")
++   (set_attr "type" "binary,binary,binary,binary,binary,binary,binary,binary,binary,binary,binary,binary,binary,binary,binary,shift,binary,binary,binary,load")
++   (set_attr "length" "*,*,*,*,*,4,4,4,4,4,4,4,4,4,4,4,4,8,8,*")
++   (set_attr "predicable" "no,no,no,no,no,yes,yes,yes,yes,yes,no,no,no,no,no,no,no,yes,no,no")
++   (set_attr "cond" "canuse,canuse,canuse,canuse,nocond,canuse,canuse,canuse,canuse,canuse,canuse_limm,nocond,nocond,nocond,nocond,nocond,canuse_limm,canuse,nocond,nocond")])
+ 
+ ; combiner splitter, pattern found in ldtoa.c .
+ ; and op3,op0,op1 / cmp op3,op2 -> add op3,op0,op4 / bmsk.f 0,op3,op1
+@@ -5717,7 +5810,6 @@
+   [(set_attr "length" "4")
+    (set_attr "type" "misc")])
+ 
+-
+ ;; FPU/FPX expands
+ 
+ ;;add
+@@ -5862,6 +5954,196 @@
+    gcc_unreachable ();
+  ")
+ 
++(define_expand "extzv"
++  [(set (match_operand:SI 0 "register_operand" "")
++	(zero_extract:SI (match_operand:SI 1 "register_operand" "")
++			 (match_operand:SI 2 "const_int_operand" "")
++			 (match_operand:SI 3 "const_int_operand" "")))]
++  "TARGET_NPS_BITOPS")
++
++; We need a sanity check in the instuction predicate because combine
++; will throw any old rubbish at us and see what sticks.
++(define_insn "*extzv_i"
++  [(set (match_operand:SI 0 "register_operand" "=Rrq")
++	(zero_extract:SI (match_operand:SI 1 "register_operand" "Rrq")
++			 (match_operand:SI 2 "const_int_operand" "n")
++			 (match_operand:SI 3 "const_int_operand" "n")))]
++  "TARGET_NPS_BITOPS && INTVAL (operands[2]) + INTVAL (operands[3]) <= 32"
++  "movb.cl %0,%1,0,%3,%2"
++  [(set_attr "type" "shift")
++   (set_attr "length" "4")])
++
++(define_expand "insv"
++  [(set (zero_extract:SI (match_operand:SI 0 "register_operand" "")
++			 (match_operand:SI 1 "const_int_operand" "")
++			 (match_operand:SI 2 "const_int_operand" ""))
++	(match_operand:SI 3 "nonmemory_operand" ""))]
++  "TARGET_NPS_BITOPS"
++{
++  int size = INTVAL (operands[1]);
++
++  if (size != 1 && size != 2 && size != 4 && size != 8)
++    operands[3] = force_reg (SImode, operands[3]);
++})
++
++(define_insn "*insv_i"
++  [(set (zero_extract:SI (match_operand:SI 0 "register_operand" "+w,Rrq")
++			 (match_operand:SI 1 "const_int_operand" "C18,n")
++			 (match_operand:SI 2 "const_int_operand" "n,n"))
++	(match_operand:SI 3 "nonmemory_operand" "P,Rrq"))]
++  "TARGET_NPS_BITOPS
++   && (register_operand (operands[3], SImode)
++       || satisfies_constraint_C18 (operands[1]))"
++  "@
++   movbi %0,%0,%3,%2,%1
++   movb %0,%0,%3,%2,0,%1"
++  [(set_attr "type" "shift")
++   (set_attr "length" "4")])
++
++(define_insn "*movb"
++  [(set (zero_extract:SI (match_operand:SI 0 "register_operand" "+Rrq")
++			 (match_operand:SI 1 "const_int_operand" "n")
++			 (match_operand:SI 2 "const_int_operand" "n"))
++	(zero_extract:SI (match_operand:SI 3 "register_operand" "Rrq")
++			 (match_dup 1)
++			 (match_operand:SI 4 "const_int_operand" "n")))]
++  "TARGET_NPS_BITOPS"
++  "movb %0,%0,%3,%2,%4,%1"
++  [(set_attr "type" "shift")
++   (set_attr "length" "4")])
++
++(define_insn "*movb_signed"
++  [(set (zero_extract:SI (match_operand:SI 0 "register_operand" "+Rrq")
++			 (match_operand:SI 1 "const_int_operand" "n")
++			 (match_operand:SI 2 "const_int_operand" "n"))
++	(sign_extract:SI (match_operand:SI 3 "register_operand" "Rrq")
++			 (match_dup 1)
++			 (match_operand:SI 4 "const_int_operand" "n")))]
++  "TARGET_NPS_BITOPS"
++  "movb %0,%0,%3,%2,%4,%1"
++  [(set_attr "type" "shift")
++   (set_attr "length" "4")])
++
++(define_insn "*movb_high"
++  [(set (zero_extract:SI (match_operand:SI 0 "register_operand" "+Rrq")
++			 (match_operand:SI 1 "const_int_operand" "n")
++			 (match_operand:SI 2 "const_int_operand" "n"))
++	(lshiftrt:SI (match_operand:SI 3 "register_operand" "Rrq")
++		     (match_operand:SI 4 "const_int_operand" "n")))]
++  "TARGET_NPS_BITOPS
++   && INTVAL (operands[4]) + INTVAL (operands[1]) <= 32"
++  "movb %0,%0,%3,%2,%4,%1"
++  [(set_attr "type" "shift")
++   (set_attr "length" "4")])
++
++; N.B.: when processing signed bitfields that fit in the top half of
++; a word, gcc will use a narrow sign extending load, and in this case
++; we will see INTVAL (operands[4]) + INTVAL (operands[1]) == 16 (or 8)
++(define_insn "*movb_high_signed"
++  [(set (zero_extract:SI (match_operand:SI 0 "register_operand" "+Rrq")
++			 (match_operand:SI 1 "const_int_operand" "n")
++			 (match_operand:SI 2 "const_int_operand" "n"))
++	(ashiftrt:SI (match_operand:SI 3 "register_operand" "Rrq")
++		     (match_operand:SI 4 "const_int_operand" "n")))]
++  "TARGET_NPS_BITOPS
++   && INTVAL (operands[4]) + INTVAL (operands[1]) <= 32"
++  "movb %0,%0,%3,%2,%4,%1"
++  [(set_attr "type" "shift")
++   (set_attr "length" "4")])
++
++(define_split
++  [(set (match_operand:SI 0 "register_operand" "")
++	(ior:SI (ashift:SI (match_operand:SI 1 "register_operand" "")
++			   (match_operand:SI 2 "const_int_operand" ""))
++		(subreg:SI (match_operand 3 "") 0)))]
++  "TARGET_NPS_BITOPS
++   && GET_MODE_BITSIZE (GET_MODE (operands[3])) <= INTVAL (operands[2])
++   && !reg_overlap_mentioned_p (operands[0], operands[1])"
++  [(set (match_dup 0) (zero_extend:SI (match_dup 3)))
++   (set (zero_extract:SI (match_dup 0) (match_dup 4) (match_dup 2))
++	(match_dup 1))]
++  "operands[4] = GEN_INT (32 - INTVAL (operands[2]));")
++
++(define_insn "*mrgb"
++  [(set (zero_extract:SI (match_operand:SI 0 "register_operand" "+Rrq")
++			 (match_operand:SI 1 "const_int_operand" "n")
++			 (match_operand:SI 2 "const_int_operand" "n"))
++	(zero_extract:SI (match_dup 0) (match_dup 1)
++			 (match_operand:SI 3 "const_int_operand" "n")))
++   (set (zero_extract:SI (match_dup 0)
++			 (match_operand:SI 4 "const_int_operand" "n")
++			 (match_operand:SI 5 "const_int_operand" "n"))
++	(zero_extract:SI (match_operand:SI 6 "register_operand" "Rrq")
++			 (match_dup 4)
++			 (match_operand:SI 7 "const_int_operand" "n")))]
++  "TARGET_NPS_BITOPS"
++{
++  output_asm_insn ("mrgb %0,%0,%6,%2,%3,%1,%5,%7,%4", operands);
++  /* The ;%? updates the known unalignment.  */
++  return arc_short_long (insn, ";%?", "nop_s");
++}
++  [(set_attr "type" "shift")
++   (set_attr "length" "6")
++   (set_attr "iscompact" "true")])
++
++;; combine fumbles combination of two movb patterns, and then the
++;; combination is rejected by combinable_i3pat.
++;; Thus, we can only use a peephole2 to combine two such insns.
++
++(define_peephole2
++  [(set (match_operand:SI 0 "register_operand" "")
++	(match_operand:SI 1 "register_operand" ""))
++   (set (zero_extract:SI (match_dup 0)
++			 (match_operand:SI 2 "const_int_operand" "")
++			 (match_operand:SI 3 "const_int_operand" ""))
++	(zero_extract:SI (match_dup 1)
++			 (match_dup 2)
++			 (match_operand:SI 4 "const_int_operand" "")))
++   (match_operand 9) ; unrelated insn scheduled here
++   (set (zero_extract:SI (match_dup 0)
++			 (match_operand:SI 5 "const_int_operand" "")
++			 (match_operand:SI 6 "const_int_operand" ""))
++	(zero_extract:SI (match_operand:SI 7 "register_operand" "")
++			 (match_dup 5)
++			 (match_operand:SI 8 "const_int_operand" "")))]
++  "TARGET_NPS_BITOPS
++   // Check that the second movb doesn't clobber an input of the extra insn.
++   && !reg_overlap_mentioned_p (operands[0], operands[9])
++   // And vice versa.
++   && !reg_set_p (operands[0], operands[9])
++   && !reg_set_p (operands[7], operands[9])"
++  [(set (match_dup 0) (match_dup 1))
++   (parallel [(set (zero_extract:SI (match_dup 0) (match_dup 1) (match_dup 2))
++		   (zero_extract:SI (match_dup 3) (match_dup 1) (match_dup 4)))
++	      (set (zero_extract:SI (match_dup 0) (match_dup 1) (match_dup 2))
++		   (zero_extract:SI (match_dup 3) (match_dup 1) (match_dup 4)))])
++   (match_dup 9)])
++
++(define_peephole2
++  [(set (match_operand:SI 0 "register_operand" "")
++	(match_operand:SI 1 "register_operand" ""))
++   (set (zero_extract:SI (match_dup 0)
++			 (match_operand:SI 2 "const_int_operand" "")
++			 (match_operand:SI 3 "const_int_operand" ""))
++	(zero_extract:SI (match_dup 1)
++			 (match_dup 2)
++			 (match_operand:SI 4 "const_int_operand" "")))
++   (set (match_dup 1) (match_operand 8))
++   (set (zero_extract:SI (match_dup 0)
++			 (match_operand:SI 5 "const_int_operand" "")
++			 (match_operand:SI 6 "const_int_operand" ""))
++	(zero_extract:SI (match_dup 1) (match_dup 5)
++			 (match_operand:SI 7 "const_int_operand" "")))]
++  "TARGET_NPS_BITOPS
++   && !reg_overlap_mentioned_p (operands[0], operands[8])"
++  [(set (match_dup 0) (match_dup 1))
++   (set (match_dup 1) (match_dup 8))
++   (parallel [(set (zero_extract:SI (match_dup 0) (match_dup 2) (match_dup 3))
++		   (zero_extract:SI (match_dup 0) (match_dup 2) (match_dup 4)))
++	      (set (zero_extract:SI (match_dup 0) (match_dup 5) (match_dup 6))
++		   (zero_extract:SI (match_dup 1) (match_dup 5) (match_dup 7)))])
++   (match_dup 1)])
++
+ ;; include the arc-FPX instructions
+ (include "fpx.md")
+ 
+diff --git a/gcc/config/arc/arc.opt b/gcc/config/arc/arc.opt
+index b2c7b3763c1d..d957a92dd6f0 100644
+--- a/gcc/config/arc/arc.opt
++++ b/gcc/config/arc/arc.opt
+@@ -470,6 +470,10 @@ Specify thread pointer register number
+ mtp-regno=none
+ Target RejectNegative Var(arc_tp_regno,-1)
+ 
++mbitops
++Target Report Var(TARGET_NPS_BITOPS) Init(TARGET_NPS_BITOPS_DEFAULT)
++Enable use of NPS400 bit operations.
++
+ mcmem
+ Target Report Var(TARGET_NPS_CMEM) Init(TARGET_NPS_CMEM_DEFAULT)
+ Enable use of NPS400 xld/xst extension.
+diff --git a/gcc/config/arc/constraints.md b/gcc/config/arc/constraints.md
+index c2992c9e9473..f30572c48579 100644
+--- a/gcc/config/arc/constraints.md
++++ b/gcc/config/arc/constraints.md
+@@ -66,10 +66,18 @@
+    Link Registers @code{ilink1}:@code{r29}, @code{ilink2}:@code{r30},
+    @code{blink}:@code{r31},")
+ 
+-(define_register_constraint "q" "ARCOMPACT16_REGS"
++(define_register_constraint "q" "TARGET_Q_CLASS ? ARCOMPACT16_REGS : NO_REGS"
+   "Registers usable in ARCompact 16-bit instructions: @code{r0}- at code{r3},
+    @code{r12}- at code{r15}")
+ 
++; NPS400 bitfield instructions require registers from the r0-r3,r12-r15
++; range, and thus we need a register class and constraint that works
++; independently of size optimization.
++(define_register_constraint
++ "Rrq" "TARGET_RRQ_CLASS ? ARCOMPACT16_REGS : NO_REGS"
++  "Registers usable in NPS400 bitfield instructions: @code{r0}- at code{r3},
++   @code{r12}- at code{r15}")
++
+ (define_register_constraint "e" "AC16_BASE_REGS"
+   "Registers usable as base-regs of memory addresses in ARCompact 16-bit memory
+    instructions: @code{r0}- at code{r3}, @code{r12}- at code{r15}, @code{sp}")
+@@ -236,12 +244,60 @@
+   (and (match_code "const_int")
+        (match_test "ival == 0xff || ival == 0xffff")))
+ 
++(define_constraint "Chs"
++ "@internal
++  constant for a highpart that can be checked with a shift (asr.f 0,rn,m)"
++  (and (match_code "const_int")
++       (match_test "IS_POWEROF2_P (-ival)")))
++
++(define_constraint "Clo"
++ "@internal
++  constant that fits into 16 lower bits, for movl"
++  (and (match_code "const_int")
++       (match_test "TARGET_NPS_BITOPS")
++       (match_test "(ival & ~0xffffU) == 0")))
++
++(define_constraint "Chi"
++ "@internal
++  constant that fits into 16 higher bits, for movh_i"
++  (and (match_code "const_int")
++       (match_test "TARGET_NPS_BITOPS")
++       (match_test "trunc_int_for_mode (ival >> 16, HImode) << 16 == ival")))
++
++(define_constraint "Cbf"
++ "@internal
++  a mask for a bit field, for AND using movb_i"
++  (and (match_code "const_int")
++       (match_test "TARGET_NPS_BITOPS")
++       (match_test "IS_POWEROF2_OR_0_P (ival + (ival & -ival))")))
++
++(define_constraint "Cbn"
++ "@internal
++  a constant integer, valid only if TARGET_NPS_BITOPS is true"
++  (and (match_code "const_int")
++       (match_test "TARGET_NPS_BITOPS")))
++
++(define_constraint "C18"
++ "@internal
++  1,2,4 or 8"
++  (and (match_code "const_int")
++       (match_test "ival == 1 || ival == 2 || ival == 4 || ival == 8")))
++
+ (define_constraint "Crr"
+  "@internal
+   constant that can be loaded with ror b,u6"
+   (and (match_code "const_int")
+        (match_test "(ival & ~0x8000001f) == 0 && !arc_ccfsm_cond_exec_p ()")))
+ 
++(define_constraint "Cbi"
++ "@internal
++  constant that can be loaded with movbi.cl"
++  (and (match_code "const_int")
++       (match_test "TARGET_NPS_BITOPS")
++       (match_test "!ival
++		    || ((ival & 0xffffffffUL) >> exact_log2 (ival & -ival)
++			<= 0xff)")))
++
+ ;; Floating-point constraints
+ 
+ (define_constraint "G"
+diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog
+index 63a13b84ee10..369383fbd07c 100644
+--- a/gcc/testsuite/ChangeLog
++++ b/gcc/testsuite/ChangeLog
+@@ -1,6 +1,22 @@
+ 2016-04-28  Joern Rennecke  <joern.rennecke at embecosm.com>
+ 	    Andrew Burgess  <andrew.burgess at embecosm.com>
+ 
++	* gcc.target/arc/extzv-1.c: New file.
++	* gcc.target/arc/insv-1.c: New file.
++	* gcc.target/arc/insv-2.c: New file.
++	* gcc.target/arc/movb-1.c: New file.
++	* gcc.target/arc/movb-2.c: New file.
++	* gcc.target/arc/movb-3.c: New file.
++	* gcc.target/arc/movb-4.c: New file.
++	* gcc.target/arc/movb-5.c: New file.
++	* gcc.target/arc/movb_cl-1.c: New file.
++	* gcc.target/arc/movb_cl-2.c: New file.
++	* gcc.target/arc/movbi_cl-1.c: New file.
++	* gcc.target/arc/movl-1.c: New file.
++
++2016-04-28  Joern Rennecke  <joern.rennecke at embecosm.com>
++	    Andrew Burgess  <andrew.burgess at embecosm.com>
++
+ 	* gcc.target/arc/cmem-1.c: New file.
+ 	* gcc.target/arc/cmem-2.c: New file.
+ 	* gcc.target/arc/cmem-3.c: New file.
+diff --git a/gcc/testsuite/gcc.target/arc/extzv-1.c b/gcc/testsuite/gcc.target/arc/extzv-1.c
+new file mode 100644
+index 000000000000..242f522f187e
+--- /dev/null
++++ b/gcc/testsuite/gcc.target/arc/extzv-1.c
+@@ -0,0 +1,11 @@
++/* { dg-do compile } */
++/* { dg-options "-mcpu=nps400 -O2 -mbitops" } */
++
++struct foo { unsigned a: 3, b: 5, c: 24; };
++
++int
++f (struct foo i)
++{
++  return i.b;
++}
++/* { dg-final { scan-assembler "movb\.cl" } } */
+diff --git a/gcc/testsuite/gcc.target/arc/insv-1.c b/gcc/testsuite/gcc.target/arc/insv-1.c
+new file mode 100644
+index 000000000000..75d47e9b1b3f
+--- /dev/null
++++ b/gcc/testsuite/gcc.target/arc/insv-1.c
+@@ -0,0 +1,21 @@
++/* { dg-do compile } */
++/* { dg-options "-mcpu=nps400 -O2 -mbitops" } */
++
++/* ??? Irrespective of insn set, generated code for this is a mess.  */
++struct foo { unsigned a: 3, b: 8, c: 21; };
++
++struct foo
++f (struct foo i)
++{
++  i.b = 42;
++  return i;
++}
++
++struct foo
++g (struct foo i, int j)
++{
++  i.b = j;
++  return i;
++}
++/* { dg-final { scan-assembler "movbi\[ \t\]" } } */
++/* { dg-final { scan-assembler "movb\[ \t\]" } } */
+diff --git a/gcc/testsuite/gcc.target/arc/insv-2.c b/gcc/testsuite/gcc.target/arc/insv-2.c
+new file mode 100644
+index 000000000000..16525511698c
+--- /dev/null
++++ b/gcc/testsuite/gcc.target/arc/insv-2.c
+@@ -0,0 +1,18 @@
++/* { dg-do compile } */
++/* { dg-options "-mcpu=nps400 -O2 -mbitops" } */
++
++struct foo { unsigned a: 3, b: 8, c: 21; } bar;
++
++void
++f (void)
++{
++  bar.b = 42;
++}
++
++void
++g (int j)
++{
++  bar.b = j;
++}
++/* { dg-final { scan-assembler "movbi\[ \t\]" } } */
++/* { dg-final { scan-assembler "movb\[ \t\]" } } */
+diff --git a/gcc/testsuite/gcc.target/arc/movb-1.c b/gcc/testsuite/gcc.target/arc/movb-1.c
+new file mode 100644
+index 000000000000..65d4ba4b6ab4
+--- /dev/null
++++ b/gcc/testsuite/gcc.target/arc/movb-1.c
+@@ -0,0 +1,13 @@
++/* { dg-do compile } */
++/* { dg-options "-mcpu=nps400 -O2 -mbitops" } */
++
++struct { unsigned a: 5, b: 8, c: 19; } foo;
++struct { unsigned a: 3, b: 8, c: 21; } bar;
++
++void
++f (void)
++{
++  bar.b = foo.b;
++}
++/* { dg-final { scan-assembler "movb\[ \t\]+r\[0-5\]+, *r\[0-5\]+, *r\[0-5\]+, *5, *3, *8" { target arceb-*-* } } } */
++/* { dg-final { scan-assembler "movb\[ \t\]+r\[0-5\]+, *r\[0-5\]+, *r\[0-5\]+, *19, *21, *8" { target arc-*-* } } } */
+diff --git a/gcc/testsuite/gcc.target/arc/movb-2.c b/gcc/testsuite/gcc.target/arc/movb-2.c
+new file mode 100644
+index 000000000000..1ba9976a566d
+--- /dev/null
++++ b/gcc/testsuite/gcc.target/arc/movb-2.c
+@@ -0,0 +1,13 @@
++/* { dg-do compile } */
++/* { dg-options "-mcpu=nps400 -O2 -mbitops" } */
++
++struct { unsigned a: 23, b: 9; } foo;
++struct { unsigned a: 23, b: 9; } bar;
++
++void
++f (void)
++{
++  bar.b = foo.b;
++}
++/* { dg-final { scan-assembler "movb\[ \t\]+r\[0-5\]+, *r\[0-5\]+, *r\[0-5\]+, *23, *23, *9" { target arc-*-* } } } */
++/* { dg-final { scan-assembler "movb\[ \t\]+r\[0-5\]+, *r\[0-5\]+, *r\[0-5\]+, *0, *0, *9" { target arceb-*-* } } } */
+diff --git a/gcc/testsuite/gcc.target/arc/movb-3.c b/gcc/testsuite/gcc.target/arc/movb-3.c
+new file mode 100644
+index 000000000000..0895154abb67
+--- /dev/null
++++ b/gcc/testsuite/gcc.target/arc/movb-3.c
+@@ -0,0 +1,13 @@
++/* { dg-do compile } */
++/* { dg-options "-mcpu=nps400 -O2 -mbitops" } */
++
++struct { int a: 23, b: 9; } foo;
++struct { int a: 23, b: 9; } bar;
++
++void
++f (void)
++{
++  bar.a = foo.a;
++}
++/* { dg-final { scan-assembler "movb\[ \t\]+r\[0-5\]+, *r\[0-5\]+, *r\[0-5\]+, *0, *0, *23" { target arc-*-* } } } */
++/* { dg-final { scan-assembler "movb\[ \t\]+r\[0-5\]+, *r\[0-5\]+, *r\[0-5\]+, *9, *9, *23" { target arceb-*-* } } } */
+diff --git a/gcc/testsuite/gcc.target/arc/movb-4.c b/gcc/testsuite/gcc.target/arc/movb-4.c
+new file mode 100644
+index 000000000000..89bf2c2b1232
+--- /dev/null
++++ b/gcc/testsuite/gcc.target/arc/movb-4.c
+@@ -0,0 +1,13 @@
++/* { dg-do compile } */
++/* { dg-options "-mcpu=nps400 -O2 -mbitops" } */
++
++struct { int a: 13, b: 19; } foo;
++struct { int a: 13, b: 19; } bar;
++
++void
++f (void)
++{
++  bar.b = foo.b;
++}
++/* { dg-final { scan-assembler "movb\[ \t\]+r\[0-5\]+, *r\[0-5\]+, *r\[0-5\]+, *13, *13, *19" { target arc-*-* } } } */
++/* { dg-final { scan-assembler "movb\[ \t\]+r\[0-5\]+, *r\[0-5\]+, *r\[0-5\]+, *0, *0, *19" { target arceb-*-* } } } */
+diff --git a/gcc/testsuite/gcc.target/arc/movb-5.c b/gcc/testsuite/gcc.target/arc/movb-5.c
+new file mode 100644
+index 000000000000..9dbe8a1e09a8
+--- /dev/null
++++ b/gcc/testsuite/gcc.target/arc/movb-5.c
+@@ -0,0 +1,13 @@
++/* { dg-do compile } */
++/* { dg-options "-mcpu=nps400 -O2 -mbitops" } */
++
++struct { int a: 23, b: 9; } foo;
++struct { int a: 23, b: 9; } bar;
++
++void
++f (void)
++{
++  bar.b = foo.b;
++}
++/* { dg-final { scan-assembler "movb\[ \t\]+r\[0-5\]+, *r\[0-5\]+, *r\[0-5\]+, *23, *(23|7), *9" { target arc-*-* } } } */
++/* { dg-final { scan-assembler "movb\[ \t\]+r\[0-5\]+, *r\[0-5\]+, *r\[0-5\]+, *0, *0, *9" { target arceb-*-* } } } */
+diff --git a/gcc/testsuite/gcc.target/arc/movb_cl-1.c b/gcc/testsuite/gcc.target/arc/movb_cl-1.c
+new file mode 100644
+index 000000000000..402250ce5302
+--- /dev/null
++++ b/gcc/testsuite/gcc.target/arc/movb_cl-1.c
+@@ -0,0 +1,9 @@
++/* { dg-do compile } */
++/* { dg-options "-mcpu=nps400 -O2 -mbitops" } */
++
++int
++f (int i)
++{
++  return i & 0x0ffff000;
++}
++/* { dg-final { scan-assembler "movb\.cl" } } */
+diff --git a/gcc/testsuite/gcc.target/arc/movb_cl-2.c b/gcc/testsuite/gcc.target/arc/movb_cl-2.c
+new file mode 100644
+index 000000000000..d2e5a944a6ea
+--- /dev/null
++++ b/gcc/testsuite/gcc.target/arc/movb_cl-2.c
+@@ -0,0 +1,11 @@
++/* { dg-do compile } */
++/* { dg-options "-mcpu=nps400 -O2 -mbitops" } */
++
++extern void g (void);
++int
++f (int i)
++{
++  if (i & 0x0ffff000)
++    g ();
++}
++/* { dg-final { scan-assembler "movb\.f\.cl" } } */
+diff --git a/gcc/testsuite/gcc.target/arc/movbi_cl-1.c b/gcc/testsuite/gcc.target/arc/movbi_cl-1.c
+new file mode 100644
+index 000000000000..3c457dbe5287
+--- /dev/null
++++ b/gcc/testsuite/gcc.target/arc/movbi_cl-1.c
+@@ -0,0 +1,9 @@
++/* { dg-do compile } */
++/* { dg-options "-mcpu=nps400 -O2 -mbitops" } */
++
++int
++f (int i)
++{
++  return 0x6e00;
++}
++/* { dg-final { scan-assembler "mov(bi|l)\.cl" } } */
+diff --git a/gcc/testsuite/gcc.target/arc/movl-1.c b/gcc/testsuite/gcc.target/arc/movl-1.c
+new file mode 100644
+index 000000000000..f1f0130a2b07
+--- /dev/null
++++ b/gcc/testsuite/gcc.target/arc/movl-1.c
+@@ -0,0 +1,17 @@
++/* { dg-do compile } */
++/* { dg-options "-mcpu=nps400 -O2 -mbitops" } */
++
++int
++f (void)
++{
++  return 0xd00d;
++}
++
++int
++g (void)
++{
++  return 0x7ff00000;
++}
++
++/* { dg-final { scan-assembler "movl\.cl\[ \t\]" } } */
++/* { dg-final { scan-assembler "movh\.cl\[ \t\]" } } */
+-- 
+2.7.4
+
diff --git a/toolchain/gcc/patches/6.3.0/0011-2016-04-28-Joern-Rennecke-joern.rennecke-embecosm.co.patch b/toolchain/gcc/patches/6.3.0/0011-2016-04-28-Joern-Rennecke-joern.rennecke-embecosm.co.patch
new file mode 100644
index 0000000..b29b994
--- /dev/null
+++ b/toolchain/gcc/patches/6.3.0/0011-2016-04-28-Joern-Rennecke-joern.rennecke-embecosm.co.patch
@@ -0,0 +1,116 @@
+From b1ed7be8931f71e970c8cffc65615421e9cd0d3e Mon Sep 17 00:00:00 2001
+From: amylaar <amylaar at 138bc75d-0d04-0410-961f-82ee72b054a4>
+Date: Thu, 28 Apr 2016 19:08:28 +0000
+Subject: [PATCH 11/89] 2016-04-28  Joern Rennecke 
+ <joern.rennecke at embecosm.com>             Andrew Burgess 
+ <andrew.burgess at embecosm.com> gcc:         * config/arc/arc.c
+ (arc_print_operand): Print integer 'H' / 'L' gcc/testsuite:         *
+ gcc.target/arc/movh_cl-1.c: New file.
+
+git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@235600 138bc75d-0d04-0410-961f-82ee72b054a4
+---
+ gcc/ChangeLog                            |  6 ++++++
+ gcc/config/arc/arc.c                     | 12 +++++-------
+ gcc/testsuite/ChangeLog                  |  5 +++++
+ gcc/testsuite/gcc.target/arc/movh_cl-1.c | 27 +++++++++++++++++++++++++++
+ 4 files changed, 43 insertions(+), 7 deletions(-)
+ create mode 100644 gcc/testsuite/gcc.target/arc/movh_cl-1.c
+
+diff --git a/gcc/ChangeLog b/gcc/ChangeLog
+index 5d03f67fa40b..0d4a3c076c27 100644
+--- a/gcc/ChangeLog
++++ b/gcc/ChangeLog
+@@ -1,6 +1,12 @@
+ 2016-04-28  Joern Rennecke  <joern.rennecke at embecosm.com>
+ 	    Andrew Burgess  <andrew.burgess at embecosm.com>
+ 
++	* config/arc/arc.c (arc_print_operand): Print integer 'H' / 'L'
++	operands as 32-bits.
++
++2016-04-28  Joern Rennecke  <joern.rennecke at embecosm.com>
++	    Andrew Burgess  <andrew.burgess at embecosm.com>
++
+ 	* config/arc/arc.c (arc_conditional_register_usage): Take
+ 	TARGET_RRQ_CLASS into account.
+ 	(arc_print_operand): Support printing 'p' and 's' operands.
+diff --git a/gcc/config/arc/arc.c b/gcc/config/arc/arc.c
+index b7dfab1e0d86..dfaea7b92412 100644
+--- a/gcc/config/arc/arc.c
++++ b/gcc/config/arc/arc.c
+@@ -3235,19 +3235,17 @@ arc_print_operand (FILE *file, rtx x, int code)
+       else if (GET_CODE (x) == CONST_INT
+ 	       || GET_CODE (x) == CONST_DOUBLE)
+ 	{
+-	  rtx first, second;
++	  rtx first, second, word;
+ 
+ 	  split_double (x, &first, &second);
+ 
+ 	  if((WORDS_BIG_ENDIAN) == 0)
+-	      fprintf (file, "0x%08" PRIx64,
+-		       code == 'L' ? INTVAL (first) : INTVAL (second));
++	    word = (code == 'L' ? first : second);
+ 	  else
+-	      fprintf (file, "0x%08" PRIx64,
+-		       code == 'L' ? INTVAL (second) : INTVAL (first));
++	    word = (code == 'L' ? second : first);
+ 
+-
+-	  }
++	  fprintf (file, "0x%08" PRIx32, ((uint32_t) INTVAL (word)));
++	}
+       else
+ 	output_operand_lossage ("invalid operand to %%H/%%L code");
+       return;
+diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog
+index 369383fbd07c..0f7f4b561168 100644
+--- a/gcc/testsuite/ChangeLog
++++ b/gcc/testsuite/ChangeLog
+@@ -1,6 +1,11 @@
+ 2016-04-28  Joern Rennecke  <joern.rennecke at embecosm.com>
+ 	    Andrew Burgess  <andrew.burgess at embecosm.com>
+ 
++	* gcc.target/arc/movh_cl-1.c: New file.
++
++2016-04-28  Joern Rennecke  <joern.rennecke at embecosm.com>
++	    Andrew Burgess  <andrew.burgess at embecosm.com>
++
+ 	* gcc.target/arc/extzv-1.c: New file.
+ 	* gcc.target/arc/insv-1.c: New file.
+ 	* gcc.target/arc/insv-2.c: New file.
+diff --git a/gcc/testsuite/gcc.target/arc/movh_cl-1.c b/gcc/testsuite/gcc.target/arc/movh_cl-1.c
+new file mode 100644
+index 000000000000..220cd9d72b94
+--- /dev/null
++++ b/gcc/testsuite/gcc.target/arc/movh_cl-1.c
+@@ -0,0 +1,27 @@
++/* { dg-do compile } */
++/* { dg-options "-mcpu=nps400 -O2 -mbitops" } */
++
++struct thing
++{
++  union
++  {
++    int raw;
++    struct
++    {
++      unsigned a : 1;
++      unsigned b : 1;
++    };
++  };
++};
++
++extern void func (int);
++
++void
++blah ()
++{
++  struct thing xx;
++  xx.a = xx.b = 1;
++  func (xx.raw);
++}
++
++/* { dg-final { scan-assembler "movh\.cl r\[0-9\]+,0xc0000000>>16" } } */
+-- 
+2.7.4
+
diff --git a/toolchain/gcc/patches/6.3.0/0012-2016-04-28-Andrew-Burgess-andrew.burgess-embecosm.co.patch b/toolchain/gcc/patches/6.3.0/0012-2016-04-28-Andrew-Burgess-andrew.burgess-embecosm.co.patch
new file mode 100644
index 0000000..38f79f5
--- /dev/null
+++ b/toolchain/gcc/patches/6.3.0/0012-2016-04-28-Andrew-Burgess-andrew.burgess-embecosm.co.patch
@@ -0,0 +1,59 @@
+From 27f2e619d6523420c05e58d63121eebf3e2bf9af Mon Sep 17 00:00:00 2001
+From: amylaar <amylaar at 138bc75d-0d04-0410-961f-82ee72b054a4>
+Date: Thu, 28 Apr 2016 19:13:47 +0000
+Subject: [PATCH 12/89] 2016-04-28  Andrew Burgess 
+ <andrew.burgess at embecosm.com>
+
+        * gcc.target/arc/nps400-1.c: New file.
+
+git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@235603 138bc75d-0d04-0410-961f-82ee72b054a4
+---
+ gcc/testsuite/ChangeLog                 |  4 ++++
+ gcc/testsuite/gcc.target/arc/nps400-1.c | 23 +++++++++++++++++++++++
+ 2 files changed, 27 insertions(+)
+ create mode 100644 gcc/testsuite/gcc.target/arc/nps400-1.c
+
+diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog
+index 0f7f4b561168..7d583c8d99dc 100644
+--- a/gcc/testsuite/ChangeLog
++++ b/gcc/testsuite/ChangeLog
+@@ -1,3 +1,7 @@
++2016-04-28  Andrew Burgess  <andrew.burgess at embecosm.com>
++
++	* gcc.target/arc/nps400-1.c: New file.
++
+ 2016-04-28  Joern Rennecke  <joern.rennecke at embecosm.com>
+ 	    Andrew Burgess  <andrew.burgess at embecosm.com>
+ 
+diff --git a/gcc/testsuite/gcc.target/arc/nps400-1.c b/gcc/testsuite/gcc.target/arc/nps400-1.c
+new file mode 100644
+index 000000000000..f3d62718bb07
+--- /dev/null
++++ b/gcc/testsuite/gcc.target/arc/nps400-1.c
+@@ -0,0 +1,23 @@
++/* { dg-do compile } */
++/* { dg-options "-mcpu=nps400 -mq-class -mbitops -munaligned-access -mcmem -O2 -fno-strict-aliasing" } */
++
++enum npsdp_mem_space_type {
++  NPSDP_EXTERNAL_MS = 1
++};
++struct npsdp_ext_addr {
++  struct {
++    struct {
++      enum npsdp_mem_space_type mem_type : 1;
++      unsigned msid : 5;
++    };
++  };
++  char user_space[];
++} a;
++char b;
++void fn1() {
++  ((struct npsdp_ext_addr *)a.user_space)->mem_type = NPSDP_EXTERNAL_MS;
++  ((struct npsdp_ext_addr *)a.user_space)->msid =
++      ((struct npsdp_ext_addr *)a.user_space)->mem_type ? 1 : 10;
++  while (b)
++    ;
++}
+-- 
+2.7.4
+
diff --git a/toolchain/gcc/patches/6.3.0/0013-ARC-Fix-unwanted-match-for-sign-extend-16-bit-consta.patch b/toolchain/gcc/patches/6.3.0/0013-ARC-Fix-unwanted-match-for-sign-extend-16-bit-consta.patch
new file mode 100644
index 0000000..0df4a88
--- /dev/null
+++ b/toolchain/gcc/patches/6.3.0/0013-ARC-Fix-unwanted-match-for-sign-extend-16-bit-consta.patch
@@ -0,0 +1,170 @@
+From 7d71e25d0b400d87b1bd55849d1a2016fed1cafe Mon Sep 17 00:00:00 2001
+From: claziss <claziss at 138bc75d-0d04-0410-961f-82ee72b054a4>
+Date: Fri, 29 Apr 2016 08:39:22 +0000
+Subject: [PATCH 13/89] [ARC] Fix unwanted match for sign extend 16-bit
+ constant.
+
+The combine pass may conclude umulhisi3_imm pattern can accept also sign
+extended 16-bit constants. This patch prohibits the combine in considering
+this pattern as suitable.
+
+gcc/
+2016-04-29  Claudiu Zissulescu  <claziss at synopsys.com>
+
+	* config/arc/arc.h (UNSIGNED_INT12, UNSIGNED_INT16): Define.
+	* config/arc/arc.md (umulhisi3): Use arc_short_operand predicate.
+	(umulhisi3_imm): Update predicates and constraint letters.
+	(umulhisi3_reg): Declare instruction as commutative.
+	* config/arc/constraints.md (J12, J16): New constraints.
+	* config/arc/predicates.md (short_unsigned_const_operand): New
+	predicate.
+	(arc_short_operand): Likewise.
+	* testsuite/gcc.target/arc/umulsihi3_z.c: New file.
+
+git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@235623 138bc75d-0d04-0410-961f-82ee72b054a4
+---
+ gcc/ChangeLog                              | 12 ++++++++++++
+ gcc/config/arc/arc.h                       |  2 ++
+ gcc/config/arc/arc.md                      | 10 +++++-----
+ gcc/config/arc/constraints.md              | 12 ++++++++++++
+ gcc/config/arc/predicates.md               |  8 ++++++++
+ gcc/testsuite/gcc.target/arc/umulsihi3_z.c | 23 +++++++++++++++++++++++
+ 6 files changed, 62 insertions(+), 5 deletions(-)
+ create mode 100644 gcc/testsuite/gcc.target/arc/umulsihi3_z.c
+
+diff --git a/gcc/ChangeLog b/gcc/ChangeLog
+index 0d4a3c076c27..e4c13b6be1e5 100644
+--- a/gcc/ChangeLog
++++ b/gcc/ChangeLog
+@@ -1,3 +1,15 @@
++2016-04-29  Claudiu Zissulescu  <claziss at synopsys.com>
++
++	* config/arc/arc.h (UNSIGNED_INT12, UNSIGNED_INT16): Define.
++	* config/arc/arc.md (umulhisi3): Use arc_short_operand predicate.
++	(umulhisi3_imm): Update predicates and constraint letters.
++	(umulhisi3_reg): Declare instruction as commutative.
++	* config/arc/constraints.md (J12, J16): New constraints.
++	* config/arc/predicates.md (short_unsigned_const_operand): New
++	predicate.
++	(arc_short_operand): Likewise.
++	* testsuite/gcc.target/arc/umulsihi3_z.c: New file.
++
+ 2016-04-28  Joern Rennecke  <joern.rennecke at embecosm.com>
+ 	    Andrew Burgess  <andrew.burgess at embecosm.com>
+ 
+diff --git a/gcc/config/arc/arc.h b/gcc/config/arc/arc.h
+index 4235eabc96d3..bc14d11ab1f9 100644
+--- a/gcc/config/arc/arc.h
++++ b/gcc/config/arc/arc.h
+@@ -815,6 +815,8 @@ extern enum reg_class arc_regno_reg_class[];
+ #define UNSIGNED_INT6(X) ((unsigned) (X) < 0x40)
+ #define UNSIGNED_INT7(X) ((unsigned) (X) < 0x80)
+ #define UNSIGNED_INT8(X) ((unsigned) (X) < 0x100)
++#define UNSIGNED_INT12(X) ((unsigned) (X) < 0x800)
++#define UNSIGNED_INT16(X) ((unsigned) (X) < 0x10000)
+ #define IS_ONE(X) ((X) == 1)
+ #define IS_ZERO(X) ((X) == 0)
+ 
+diff --git a/gcc/config/arc/arc.md b/gcc/config/arc/arc.md
+index 7c30eb46e072..d1a9159411da 100644
+--- a/gcc/config/arc/arc.md
++++ b/gcc/config/arc/arc.md
+@@ -1820,7 +1820,7 @@
+ (define_expand "umulhisi3"
+   [(set (match_operand:SI 0 "register_operand"                           "")
+ 	(mult:SI (zero_extend:SI (match_operand:HI 1 "register_operand"  ""))
+-		 (zero_extend:SI (match_operand:HI 2 "nonmemory_operand" ""))))]
++		 (zero_extend:SI (match_operand:HI 2 "arc_short_operand" ""))))]
+   "TARGET_MPYW"
+   "{
+     if (CONSTANT_P (operands[2]))
+@@ -1832,9 +1832,9 @@
+ )
+ 
+ (define_insn "umulhisi3_imm"
+-  [(set (match_operand:SI 0 "register_operand"                          "=r, r,r,  r,  r")
+-	(mult:SI (zero_extend:SI (match_operand:HI 1 "register_operand" " 0, r,0,  0,  r"))
+-		 (match_operand:HI 2 "short_const_int_operand"          " L, L,I,C16,C16")))]
++  [(set (match_operand:SI 0 "register_operand"                          "=r, r,  r,  r,  r")
++	(mult:SI (zero_extend:SI (match_operand:HI 1 "register_operand" "%0, r,  0,  0,  r"))
++		 (match_operand:HI 2 "short_unsigned_const_operand"     " L, L,J12,J16,J16")))]
+   "TARGET_MPYW"
+   "mpyuw%? %0,%1,%2"
+   [(set_attr "length" "4,4,4,8,8")
+@@ -1846,7 +1846,7 @@
+ 
+ (define_insn "umulhisi3_reg"
+   [(set (match_operand:SI 0 "register_operand"                          "=Rcqq, r, r")
+-	(mult:SI (zero_extend:SI (match_operand:HI 1 "register_operand" "    0, 0, r"))
++	(mult:SI (zero_extend:SI (match_operand:HI 1 "register_operand" "   %0, 0, r"))
+ 		 (zero_extend:SI (match_operand:HI 2 "register_operand" " Rcqq, r, r"))))]
+   "TARGET_MPYW"
+   "mpyuw%? %0,%1,%2"
+diff --git a/gcc/config/arc/constraints.md b/gcc/config/arc/constraints.md
+index f30572c48579..5069d7d9746d 100644
+--- a/gcc/config/arc/constraints.md
++++ b/gcc/config/arc/constraints.md
+@@ -499,3 +499,15 @@
+ (define_memory_constraint "ATO"
+   "A memory with only a base register"
+   (match_operand 0 "mem_noofs_operand"))
++
++(define_constraint "J12"
++  "@internal
++   An unsigned 12-bit integer constant."
++  (and (match_code "const_int")
++       (match_test "UNSIGNED_INT12 (ival)")))
++
++(define_constraint "J16"
++  "@internal
++   An unsigned 16-bit integer constant"
++  (and (match_code "const_int")
++       (match_test "UNSIGNED_INT16 (ival)")))
+diff --git a/gcc/config/arc/predicates.md b/gcc/config/arc/predicates.md
+index 0d2e217bf9d6..8e4b4b40c543 100644
+--- a/gcc/config/arc/predicates.md
++++ b/gcc/config/arc/predicates.md
+@@ -838,3 +838,11 @@
+   (ior (match_operand:SI 0 "cmem_address_0")
+        (match_operand:SI 0 "cmem_address_1")
+        (match_operand:SI 0 "cmem_address_2")))
++
++(define_predicate "short_unsigned_const_operand"
++  (and (match_code "const_int")
++       (match_test "satisfies_constraint_J16 (op)")))
++
++(define_predicate "arc_short_operand"
++  (ior (match_test "register_operand (op, mode)")
++       (match_test "short_unsigned_const_operand (op, mode)")))
+diff --git a/gcc/testsuite/gcc.target/arc/umulsihi3_z.c b/gcc/testsuite/gcc.target/arc/umulsihi3_z.c
+new file mode 100644
+index 000000000000..cf1c00d806ac
+--- /dev/null
++++ b/gcc/testsuite/gcc.target/arc/umulsihi3_z.c
+@@ -0,0 +1,23 @@
++/* Check if the optimizers are not removing the umulsihi3_imm
++   instruction.  */
++/* { dg-do run } */
++/* { dg-options "-O2 -fno-inline" } */
++
++#include <stdint.h>
++
++static int32_t test (int16_t reg_val)
++{
++  int32_t x = (reg_val & 0xf) * 62500;
++  return x;
++}
++
++int main (void)
++{
++  volatile int32_t x = 0xc172;
++  x = test (x);
++
++  if (x != 0x0001e848)
++    __builtin_abort ();
++  return 0;
++}
++
+-- 
+2.7.4
+
diff --git a/toolchain/gcc/patches/6.3.0/0014-ARC-Fix-obsolete-constraint.patch b/toolchain/gcc/patches/6.3.0/0014-ARC-Fix-obsolete-constraint.patch
new file mode 100644
index 0000000..9706a91
--- /dev/null
+++ b/toolchain/gcc/patches/6.3.0/0014-ARC-Fix-obsolete-constraint.patch
@@ -0,0 +1,72 @@
+From 2825bab71dba8b30e45d7cb1b5885b6107a70a19 Mon Sep 17 00:00:00 2001
+From: claziss <claziss at 138bc75d-0d04-0410-961f-82ee72b054a4>
+Date: Fri, 29 Apr 2016 10:11:25 +0000
+Subject: [PATCH 14/89] [ARC] Fix obsolete constraint.
+
+include/
+2016-04-29  Claudiu Zissulescu  <claziss at synopsys.com>
+
+	* longlong.h (add_ssaaaa): Replace obsolete 'J' constraint with
+	'Cal' constraint.
+	(sub_ddmmss): Likewise.
+
+git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@235631 138bc75d-0d04-0410-961f-82ee72b054a4
+---
+ include/ChangeLog  |  6 ++++++
+ include/longlong.h | 12 ++++++------
+ 2 files changed, 12 insertions(+), 6 deletions(-)
+
+diff --git a/include/ChangeLog b/include/ChangeLog
+index 72a60fd48a95..429da9da7139 100644
+--- a/include/ChangeLog
++++ b/include/ChangeLog
+@@ -1,3 +1,9 @@
++2016-04-29  Claudiu Zissulescu  <claziss at synopsys.com>
++
++	* longlong.h (add_ssaaaa): Replace obsolete 'J' constraint with
++	'Cal' constraint.
++	(sub_ddmmss): Likewise.
++
+ 2016-12-21  Release Manager
+ 
+ 	* GCC 6.3.0 released.
+diff --git a/include/longlong.h b/include/longlong.h
+index 34ad9b4f5710..03fd2a1ae4c3 100644
+--- a/include/longlong.h
++++ b/include/longlong.h
+@@ -197,17 +197,17 @@ extern UDItype __udiv_qrnnd (UDItype *, UDItype, UDItype, UDItype);
+ 	   : "=r" ((USItype) (sh)),					\
+ 	     "=&r" ((USItype) (sl))					\
+ 	   : "%r" ((USItype) (ah)),					\
+-	     "rIJ" ((USItype) (bh)),					\
++	     "rICal" ((USItype) (bh)),					\
+ 	     "%r" ((USItype) (al)),					\
+-	     "rIJ" ((USItype) (bl)))
++	     "rICal" ((USItype) (bl)))
+ #define sub_ddmmss(sh, sl, ah, al, bh, bl) \
+   __asm__ ("sub.f	%1, %4, %5\n\tsbc	%0, %2, %3"		\
+ 	   : "=r" ((USItype) (sh)),					\
+ 	     "=&r" ((USItype) (sl))					\
+ 	   : "r" ((USItype) (ah)),					\
+-	     "rIJ" ((USItype) (bh)),					\
++	     "rICal" ((USItype) (bh)),					\
+ 	     "r" ((USItype) (al)),					\
+-	     "rIJ" ((USItype) (bl)))
++	     "rICal" ((USItype) (bl)))
+ 
+ #define __umulsidi3(u,v) ((UDItype)(USItype)u*(USItype)v)
+ #ifdef __ARC_NORM__
+@@ -221,8 +221,8 @@ extern UDItype __udiv_qrnnd (UDItype *, UDItype, UDItype, UDItype);
+     }									\
+   while (0)
+ #define COUNT_LEADING_ZEROS_0 32
+-#endif
+-#endif
++#endif /* __ARC_NORM__ */
++#endif /* __arc__ */
+ 
+ #if defined (__arm__) && (defined (__thumb2__) || !defined (__thumb__)) \
+  && W_TYPE_SIZE == 32
+-- 
+2.7.4
+
diff --git a/toolchain/gcc/patches/6.3.0/0015-ARC-Handle-FPX-NaN-within-optimized-floating-point-l.patch b/toolchain/gcc/patches/6.3.0/0015-ARC-Handle-FPX-NaN-within-optimized-floating-point-l.patch
new file mode 100644
index 0000000..f9cc3cc
--- /dev/null
+++ b/toolchain/gcc/patches/6.3.0/0015-ARC-Handle-FPX-NaN-within-optimized-floating-point-l.patch
@@ -0,0 +1,133 @@
+From d633237810ddded2096a5d56981e55ae49e89614 Mon Sep 17 00:00:00 2001
+From: claziss <claziss at 138bc75d-0d04-0410-961f-82ee72b054a4>
+Date: Fri, 29 Apr 2016 10:49:26 +0000
+Subject: [PATCH 15/89] [ARC] Handle FPX NaN within optimized floating point
+ library.
+
+gcc/
+2016-04-29  Claudiu Zissulescu  <claziss at synopsys.com>
+
+	* testsuite/gcc.target/arc/ieee_eq.c: New test.
+
+libgcc/
+2016-04-29  Claudiu Zissulescu  <claziss at synopsys.com>
+
+	* config/arc/ieee-754/eqdf2.S: Handle FPX NaN.
+
+git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@235633 138bc75d-0d04-0410-961f-82ee72b054a4
+---
+ gcc/ChangeLog                          |  4 +++
+ gcc/testsuite/gcc.target/arc/ieee_eq.c | 47 ++++++++++++++++++++++++++++++++++
+ libgcc/ChangeLog                       |  4 +++
+ libgcc/config/arc/ieee-754/eqdf2.S     | 15 +++++++----
+ 4 files changed, 65 insertions(+), 5 deletions(-)
+ create mode 100644 gcc/testsuite/gcc.target/arc/ieee_eq.c
+
+diff --git a/gcc/ChangeLog b/gcc/ChangeLog
+index e4c13b6be1e5..55d8f825478f 100644
+--- a/gcc/ChangeLog
++++ b/gcc/ChangeLog
+@@ -1,5 +1,9 @@
+ 2016-04-29  Claudiu Zissulescu  <claziss at synopsys.com>
+ 
++	* testsuite/gcc.target/arc/ieee_eq.c: New test.
++
++2016-04-29  Claudiu Zissulescu  <claziss at synopsys.com>
++
+ 	* config/arc/arc.h (UNSIGNED_INT12, UNSIGNED_INT16): Define.
+ 	* config/arc/arc.md (umulhisi3): Use arc_short_operand predicate.
+ 	(umulhisi3_imm): Update predicates and constraint letters.
+diff --git a/gcc/testsuite/gcc.target/arc/ieee_eq.c b/gcc/testsuite/gcc.target/arc/ieee_eq.c
+new file mode 100644
+index 000000000000..70aebad063bc
+--- /dev/null
++++ b/gcc/testsuite/gcc.target/arc/ieee_eq.c
+@@ -0,0 +1,47 @@
++/* { dg-do run } */
++/* { dg-options "-O2" } */
++
++#include <stdio.h>
++#include <float.h>
++
++#define TEST_EQ(TYPE,X,Y,RES)				\
++  do {							\
++    volatile TYPE a, b;					\
++    a = (TYPE) X;					\
++    b = (TYPE) Y;					\
++    if ((a == b) != RES)				\
++      {							\
++	printf ("Runtime computation error @%d. %g "	\
++		"!= %g\n", __LINE__, a, b);		\
++	error = 1;					\
++      }							\
++  } while (0)
++
++#ifndef __HS__
++/* Special type of NaN found when using double FPX instructions.  */
++static const unsigned long long __nan = 0x7FF0000080000000ULL;
++# define W (*(double *) &__nan)
++#else
++# define W __builtin_nan ("")
++#endif
++
++#define Q __builtin_nan ("")
++#define H __builtin_inf ()
++
++int main (void)
++{
++  int error = 0;
++
++  TEST_EQ (double, 1, 1, 1);
++  TEST_EQ (double, 1, 2, 0);
++  TEST_EQ (double, W, W, 0);
++  TEST_EQ (double, Q, Q, 0);
++  TEST_EQ (double, __DBL_MAX__, __DBL_MAX__, 1);
++  TEST_EQ (double, __DBL_MIN__, __DBL_MIN__, 1);
++  TEST_EQ (double, H, H, 1);
++
++  if (error)
++    __builtin_abort ();
++
++  return 0;
++}
+diff --git a/libgcc/ChangeLog b/libgcc/ChangeLog
+index 0993d6226cd2..ac1ab461a8bb 100644
+--- a/libgcc/ChangeLog
++++ b/libgcc/ChangeLog
+@@ -1,3 +1,7 @@
++2016-04-29  Claudiu Zissulescu  <claziss at synopsys.com>
++
++	* config/arc/ieee-754/eqdf2.S: Handle FPX NaN.
++
+ 2016-04-28  Claudiu Zissulescu  <claziss at synopsys.com>
+ 	    Joern Rennecke  <joern.rennecke at embecosm.com>
+ 
+diff --git a/libgcc/config/arc/ieee-754/eqdf2.S b/libgcc/config/arc/ieee-754/eqdf2.S
+index bc7d88e838da..7e80ef52b2a8 100644
+--- a/libgcc/config/arc/ieee-754/eqdf2.S
++++ b/libgcc/config/arc/ieee-754/eqdf2.S
+@@ -58,11 +58,16 @@ __eqdf2:
+ 	   well predictable (as seen from the branch predictor).  */
+ __eqdf2:
+ 	brne.d DBL0H,DBL1H,.Lhighdiff
+-	bmsk r12,DBL0H,20
+-#ifdef DPFP_COMPAT
+-	or.f 0,DBL0L,DBL1L
+-	bset.ne r12,r12,21
+-#endif /* DPFP_COMPAT */
++#ifndef __HS__
++	/* The next two instructions are required to recognize the FPX
++	NaN, which has a pattern like this: 0x7ff0_0000_8000_0000, as
++	oposite to 0x7ff8_0000_0000_0000.  */
++	or.f    0,DBL0L,DBL1L
++	mov_s	r12,0x00200000
++	bset.ne r12,r12,0
++#else
++	bmsk    r12,DBL0H,20
++#endif /* __HS__ */
+ 	add1.f	r12,r12,DBL0H /* set c iff NaN; also, clear z if NaN.  */
+ 	j_s.d	[blink]
+ 	cmp.cc	DBL0L,DBL1L
+-- 
+2.7.4
+
diff --git a/toolchain/gcc/patches/6.3.0/0016-2016-04-29-Andrew-Burgess-andrew.burgess-embecosm.co.patch b/toolchain/gcc/patches/6.3.0/0016-2016-04-29-Andrew-Burgess-andrew.burgess-embecosm.co.patch
new file mode 100644
index 0000000..41f0860
--- /dev/null
+++ b/toolchain/gcc/patches/6.3.0/0016-2016-04-29-Andrew-Burgess-andrew.burgess-embecosm.co.patch
@@ -0,0 +1,123 @@
+From 9eb16132cfed12dc87c50c02e58db1554607b92a Mon Sep 17 00:00:00 2001
+From: amylaar <amylaar at 138bc75d-0d04-0410-961f-82ee72b054a4>
+Date: Fri, 29 Apr 2016 12:07:31 +0000
+Subject: [PATCH 16/89] 2016-04-29  Andrew Burgess 
+ <andrew.burgess at embecosm.com>
+
+        * config/arc/arc.md (*loadqi_update): Replace use of 'rI'
+        constraint with 'rCm2' constraints to limit possible immediate
+        size.
+        (*load_zeroextendqisi_update): Likewise.
+        (*load_signextendqisi_update): Likewise.
+        (*loadhi_update): Likewise.
+        (*load_zeroextendhisi_update): Likewise.
+        (*load_signextendhisi_update): Likewise.
+        (*loadsi_update): Likewise.
+        (*loadsf_update): Likewise.
+
+git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@235636 138bc75d-0d04-0410-961f-82ee72b054a4
+---
+ gcc/ChangeLog         | 13 +++++++++++++
+ gcc/config/arc/arc.md | 16 ++++++++--------
+ 2 files changed, 21 insertions(+), 8 deletions(-)
+
+diff --git a/gcc/ChangeLog b/gcc/ChangeLog
+index 55d8f825478f..2db7b54b57a8 100644
+--- a/gcc/ChangeLog
++++ b/gcc/ChangeLog
+@@ -1,3 +1,16 @@
++2016-04-29  Andrew Burgess  <andrew.burgess at embecosm.com>
++
++	* config/arc/arc.md (*loadqi_update): Replace use of 'rI'
++	constraint with 'rCm2' constraints to limit possible immediate
++	size.
++	(*load_zeroextendqisi_update): Likewise.
++	(*load_signextendqisi_update): Likewise.
++	(*loadhi_update): Likewise.
++	(*load_zeroextendhisi_update): Likewise.
++	(*load_signextendhisi_update): Likewise.
++	(*loadsi_update): Likewise.
++	(*loadsf_update): Likewise.
++
+ 2016-04-29  Claudiu Zissulescu  <claziss at synopsys.com>
+ 
+ 	* testsuite/gcc.target/arc/ieee_eq.c: New test.
+diff --git a/gcc/config/arc/arc.md b/gcc/config/arc/arc.md
+index d1a9159411da..c61107f4b416 100644
+--- a/gcc/config/arc/arc.md
++++ b/gcc/config/arc/arc.md
+@@ -1254,7 +1254,7 @@
+   [(set (match_operand:QI 3 "dest_reg_operand" "=r,r")
+         (match_operator:QI 4 "any_mem_operand"
+          [(plus:SI (match_operand:SI 1 "register_operand" "0,0")
+-                   (match_operand:SI 2 "nonmemory_operand" "rI,Cal"))]))
++                   (match_operand:SI 2 "nonmemory_operand" "rCm2,Cal"))]))
+    (set (match_operand:SI 0 "dest_reg_operand" "=r,r")
+ 	(plus:SI (match_dup 1) (match_dup 2)))]
+   ""
+@@ -1266,7 +1266,7 @@
+   [(set (match_operand:SI 3 "dest_reg_operand" "=r,r")
+ 	(zero_extend:SI (match_operator:QI 4 "any_mem_operand"
+ 			 [(plus:SI (match_operand:SI 1 "register_operand" "0,0")
+-			           (match_operand:SI 2 "nonmemory_operand" "rI,Cal"))])))
++			           (match_operand:SI 2 "nonmemory_operand" "rCm2,Cal"))])))
+    (set (match_operand:SI 0 "dest_reg_operand" "=r,r")
+ 	(plus:SI (match_dup 1) (match_dup 2)))]
+   ""
+@@ -1278,7 +1278,7 @@
+   [(set (match_operand:SI 3 "dest_reg_operand" "=r,r")
+ 	(sign_extend:SI (match_operator:QI 4 "any_mem_operand"
+ 			 [(plus:SI (match_operand:SI 1 "register_operand" "0,0")
+-			           (match_operand:SI 2 "nonmemory_operand" "rI,Cal"))])))
++			           (match_operand:SI 2 "nonmemory_operand" "rCm2,Cal"))])))
+    (set (match_operand:SI 0 "dest_reg_operand" "=r,r")
+ 	(plus:SI (match_dup 1) (match_dup 2)))]
+   ""
+@@ -1304,7 +1304,7 @@
+   [(set (match_operand:HI 3 "dest_reg_operand" "=r,r")
+ 	(match_operator:HI 4 "any_mem_operand"
+ 	 [(plus:SI (match_operand:SI 1 "register_operand" "0,0")
+-	           (match_operand:SI 2 "nonmemory_operand" "rI,Cal"))]))
++	           (match_operand:SI 2 "nonmemory_operand" "rCm2,Cal"))]))
+    (set (match_operand:SI 0 "dest_reg_operand" "=w,w")
+ 	(plus:SI (match_dup 1) (match_dup 2)))]
+   ""
+@@ -1316,7 +1316,7 @@
+   [(set (match_operand:SI 3 "dest_reg_operand" "=r,r")
+ 	(zero_extend:SI (match_operator:HI 4 "any_mem_operand"
+ 			 [(plus:SI (match_operand:SI 1 "register_operand" "0,0")
+-			           (match_operand:SI 2 "nonmemory_operand" "rI,Cal"))])))
++			           (match_operand:SI 2 "nonmemory_operand" "rCm2,Cal"))])))
+    (set (match_operand:SI 0 "dest_reg_operand" "=r,r")
+ 	(plus:SI (match_dup 1) (match_dup 2)))]
+   ""
+@@ -1329,7 +1329,7 @@
+   [(set (match_operand:SI 3 "dest_reg_operand" "=r,r")
+ 	(sign_extend:SI (match_operator:HI 4 "any_mem_operand"
+ 			 [(plus:SI (match_operand:SI 1 "register_operand" "0,0")
+-			           (match_operand:SI 2 "nonmemory_operand" "rI,Cal"))])))
++			           (match_operand:SI 2 "nonmemory_operand" "rCm2,Cal"))])))
+    (set (match_operand:SI 0 "dest_reg_operand" "=w,w")
+ 	(plus:SI (match_dup 1) (match_dup 2)))]
+   ""
+@@ -1354,7 +1354,7 @@
+   [(set (match_operand:SI 3 "dest_reg_operand" "=r,r")
+ 	(match_operator:SI 4 "any_mem_operand"
+ 	 [(plus:SI (match_operand:SI 1 "register_operand" "0,0")
+-	           (match_operand:SI 2 "nonmemory_operand" "rI,Cal"))]))
++	           (match_operand:SI 2 "nonmemory_operand" "rCm2,Cal"))]))
+    (set (match_operand:SI 0 "dest_reg_operand" "=w,w")
+ 	(plus:SI (match_dup 1) (match_dup 2)))]
+   ""
+@@ -1378,7 +1378,7 @@
+   [(set (match_operand:SF 3 "dest_reg_operand" "=r,r")
+ 	(match_operator:SF 4 "any_mem_operand"
+ 	 [(plus:SI (match_operand:SI 1 "register_operand" "0,0")
+-	           (match_operand:SI 2 "nonmemory_operand" "rI,Cal"))]))
++	           (match_operand:SI 2 "nonmemory_operand" "rCm2,Cal"))]))
+    (set (match_operand:SI 0 "dest_reg_operand" "=w,w")
+ 	(plus:SI (match_dup 1) (match_dup 2)))]
+   ""
+-- 
+2.7.4
+
diff --git a/toolchain/gcc/patches/6.3.0/0017-ARC-Add-new-ARCv2-instructions.patch b/toolchain/gcc/patches/6.3.0/0017-ARC-Add-new-ARCv2-instructions.patch
new file mode 100644
index 0000000..f70d026
--- /dev/null
+++ b/toolchain/gcc/patches/6.3.0/0017-ARC-Add-new-ARCv2-instructions.patch
@@ -0,0 +1,785 @@
+From a2e3ff8463164c3c530d92a691e27b522289dd5b Mon Sep 17 00:00:00 2001
+From: claziss <claziss at 138bc75d-0d04-0410-961f-82ee72b054a4>
+Date: Mon, 2 May 2016 08:54:34 +0000
+Subject: [PATCH 17/89] [ARC] Add new ARCv2 instructions.
+
+gcc/
+2016-05-02  Claudiu Zissulescu  <claziss at synopsys.com>
+
+	* config/arc/arc-protos.h (compact_memory_operand_p): Declare.
+	* config/arc/arc.c (arc_output_commutative_cond_exec): Consider
+	bmaskn instruction.
+	(arc_dwarf_register_span): Remove enum keyword.
+	(compact_memory_operand_p): New function.
+	* config/arc/arc.h (reg_class): Add code density register classes.
+	(REG_CLASS_NAMES): Likewise.
+	(REG_CLASS_CONTENTS): Likewise.
+	* config/arc/arc.md (*movqi_insn): Add code density instructions.
+	(*movhi_insn, *movsi_insn, *movsf_insn): Likewise.
+	(*extendhisi2_i, andsi3_i, cmpsi_cc_insn_mixed): Likewise.
+	(*cmpsi_cc_c_insn, *movsi_ne): Likewise.
+	* config/arc/constraints.md (C2p, Uts, Cm1, Cm3, Ucd): New
+	constraints.
+	(h, Rcd, Rsd, Rzd): New register constraints.
+	(T): Use compact_memory_operand_p function.
+	* config/arc/predicates.md (compact_load_memory_operand): Remove.
+
+git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@235707 138bc75d-0d04-0410-961f-82ee72b054a4
+---
+ gcc/ChangeLog                 |  20 ++++++
+ gcc/config/arc/arc-protos.h   |   2 +-
+ gcc/config/arc/arc.c          | 146 +++++++++++++++++++++++++++++++++++++++
+ gcc/config/arc/arc.h          |   9 +++
+ gcc/config/arc/arc.md         | 154 ++++++++++++++++++++++++------------------
+ gcc/config/arc/constraints.md |  61 ++++++++++++++++-
+ gcc/config/arc/predicates.md  |  89 ------------------------
+ 7 files changed, 324 insertions(+), 157 deletions(-)
+
+diff --git a/gcc/ChangeLog b/gcc/ChangeLog
+index 2db7b54b57a8..cedbe6eb44f2 100644
+--- a/gcc/ChangeLog
++++ b/gcc/ChangeLog
+@@ -1,3 +1,23 @@
++2016-05-02  Claudiu Zissulescu  <claziss at synopsys.com>
++
++	* config/arc/arc-protos.h (compact_memory_operand_p): Declare.
++	* config/arc/arc.c (arc_output_commutative_cond_exec): Consider
++	bmaskn instruction.
++	(arc_dwarf_register_span): Remove enum keyword.
++	(compact_memory_operand_p): New function.
++	* config/arc/arc.h (reg_class): Add code density register classes.
++	(REG_CLASS_NAMES): Likewise.
++	(REG_CLASS_CONTENTS): Likewise.
++	* config/arc/arc.md (*movqi_insn): Add code density instructions.
++	(*movhi_insn, *movsi_insn, *movsf_insn): Likewise.
++	(*extendhisi2_i, andsi3_i, cmpsi_cc_insn_mixed): Likewise.
++	(*cmpsi_cc_c_insn, *movsi_ne): Likewise.
++	* config/arc/constraints.md (C2p, Uts, Cm1, Cm3, Ucd): New
++	constraints.
++	(h, Rcd, Rsd, Rzd): New register constraints.
++	(T): Use compact_memory_operand_p function.
++	* config/arc/predicates.md (compact_load_memory_operand): Remove.
++
+ 2016-04-29  Andrew Burgess  <andrew.burgess at embecosm.com>
+ 
+ 	* config/arc/arc.md (*loadqi_update): Replace use of 'rI'
+diff --git a/gcc/config/arc/arc-protos.h b/gcc/config/arc/arc-protos.h
+index 3bf28a088bd9..8630e2d84daa 100644
+--- a/gcc/config/arc/arc-protos.h
++++ b/gcc/config/arc/arc-protos.h
+@@ -44,7 +44,7 @@ extern void emit_shift (enum rtx_code, rtx, rtx, rtx);
+ extern void arc_expand_atomic_op (enum rtx_code, rtx, rtx, rtx, rtx, rtx);
+ extern void arc_split_compare_and_swap (rtx *);
+ extern void arc_expand_compare_and_swap (rtx *);
+-
++extern bool compact_memory_operand_p (rtx, machine_mode, bool, bool);
+ #endif /* RTX_CODE */
+ 
+ #ifdef TREE_CODE
+diff --git a/gcc/config/arc/arc.c b/gcc/config/arc/arc.c
+index dfaea7b92412..a54fddb45d32 100644
+--- a/gcc/config/arc/arc.c
++++ b/gcc/config/arc/arc.c
+@@ -7389,6 +7389,11 @@ arc_output_commutative_cond_exec (rtx *operands, bool output_p)
+       case AND:
+ 	if (satisfies_constraint_C1p (operands[2]))
+ 	  pat = "bmsk%? %0,%1,%Z2";
++	else if (satisfies_constraint_C2p (operands[2]))
++	  {
++	    operands[2] = GEN_INT ((~INTVAL (operands[2])));
++	    pat = "bmskn%? %0,%1,%Z2";
++	  }
+ 	else if (satisfies_constraint_Ccp (operands[2]))
+ 	  pat = "bclr%? %0,%1,%M2";
+ 	else if (satisfies_constraint_CnL (operands[2]))
+@@ -9859,12 +9864,153 @@ arc_dwarf_register_span (rtx rtl)
+ 
+ /* We can't inline this in INSN_REFERENCES_ARE_DELAYED because
+    resource.h doesn't include the required header files.  */
++
+ bool
+ insn_is_tls_gd_dispatch (rtx_insn *insn)
+ {
+   return recog_memoized (insn) == CODE_FOR_tls_gd_dispatch;
+ }
+ 
++/* Return true if OP is an acceptable memory operand for ARCompact
++   16-bit load instructions of MODE.
++
++   AV2SHORT: TRUE if address needs to fit into the new ARCv2 short
++   non scaled instructions.
++
++   SCALED: TRUE if address can be scaled.  */
++
++bool
++compact_memory_operand_p (rtx op, machine_mode mode,
++			  bool av2short, bool scaled)
++{
++  rtx addr, plus0, plus1;
++  int size, off;
++
++  /* Eliminate non-memory operations.  */
++  if (GET_CODE (op) != MEM)
++    return 0;
++
++  /* .di instructions have no 16-bit form.  */
++  if (MEM_VOLATILE_P (op) && !TARGET_VOLATILE_CACHE_SET)
++    return false;
++
++  if (mode == VOIDmode)
++    mode = GET_MODE (op);
++
++  size = GET_MODE_SIZE (mode);
++
++  /* dword operations really put out 2 instructions, so eliminate
++     them.  */
++  if (size > UNITS_PER_WORD)
++    return false;
++
++  /* Decode the address now.  */
++  addr = XEXP (op, 0);
++  switch (GET_CODE (addr))
++    {
++    case REG:
++      return (REGNO (addr) >= FIRST_PSEUDO_REGISTER
++	      || COMPACT_GP_REG_P (REGNO (addr))
++	      || (SP_REG_P (REGNO (addr)) && (size != 2)));
++    case PLUS:
++      plus0 = XEXP (addr, 0);
++      plus1 = XEXP (addr, 1);
++
++      if ((GET_CODE (plus0) == REG)
++	  && ((REGNO (plus0) >= FIRST_PSEUDO_REGISTER)
++	      || COMPACT_GP_REG_P (REGNO (plus0)))
++	  && ((GET_CODE (plus1) == REG)
++	      && ((REGNO (plus1) >= FIRST_PSEUDO_REGISTER)
++		  || COMPACT_GP_REG_P (REGNO (plus1)))))
++	{
++	  return !av2short;
++	}
++
++      if ((GET_CODE (plus0) == REG)
++	  && ((REGNO (plus0) >= FIRST_PSEUDO_REGISTER)
++	      || (COMPACT_GP_REG_P (REGNO (plus0)) && !av2short)
++	      || (IN_RANGE (REGNO (plus0), 0, 31) && av2short))
++	  && (GET_CODE (plus1) == CONST_INT))
++	{
++	  bool valid = false;
++
++	  off = INTVAL (plus1);
++
++	  /* Negative offset is not supported in 16-bit load/store insns.  */
++	  if (off < 0)
++	    return 0;
++
++	  /* Only u5 immediates allowed in code density instructions.  */
++	  if (av2short)
++	    {
++	      switch (size)
++		{
++		case 1:
++		  return false;
++		case 2:
++		  /* This is an ldh_s.x instruction, check the u6
++		     immediate.  */
++		  if (COMPACT_GP_REG_P (REGNO (plus0)))
++		    valid = true;
++		  break;
++		case 4:
++		  /* Only u5 immediates allowed in 32bit access code
++		     density instructions.  */
++		  if (REGNO (plus0) <= 31)
++		    return ((off < 32) && (off % 4 == 0));
++		  break;
++		default:
++		  return false;
++		}
++	    }
++	  else
++	    if (COMPACT_GP_REG_P (REGNO (plus0)))
++	      valid = true;
++
++	  if (valid)
++	    {
++
++	      switch (size)
++		{
++		case 1:
++		  return (off < 32);
++		case 2:
++		  /* The 6-bit constant get shifted to fit the real
++		     5-bits field.  Check also for the alignment.  */
++		  return ((off < 64) && (off % 2 == 0));
++		case 4:
++		  return ((off < 128) && (off % 4 == 0));
++		default:
++		  return false;
++		}
++	    }
++	}
++
++      if (REG_P (plus0) && CONST_INT_P (plus1)
++	  && ((REGNO (plus0) >= FIRST_PSEUDO_REGISTER)
++	      || SP_REG_P (REGNO (plus0)))
++	  && !av2short)
++	{
++	  off = INTVAL (plus1);
++	  return ((size != 2) && (off >= 0 && off < 128) && (off % 4 == 0));
++	}
++
++      if ((GET_CODE (plus0) == MULT)
++	  && (GET_CODE (XEXP (plus0, 0)) == REG)
++	  && ((REGNO (XEXP (plus0, 0)) >= FIRST_PSEUDO_REGISTER)
++	      || COMPACT_GP_REG_P (REGNO (XEXP (plus0, 0))))
++	  && (GET_CODE (plus1) == REG)
++	  && ((REGNO (plus1) >= FIRST_PSEUDO_REGISTER)
++	      || COMPACT_GP_REG_P (REGNO (plus1))))
++	return scaled;
++    default:
++      break ;
++      /* TODO: 'gp' and 'pcl' are to supported as base address operand
++	 for 16-bit load instructions.  */
++    }
++  return false;
++}
++
+ struct gcc_target targetm = TARGET_INITIALIZER;
+ 
+ #include "gt-arc.h"
+diff --git a/gcc/config/arc/arc.h b/gcc/config/arc/arc.h
+index bc14d11ab1f9..f6b85ea7e51b 100644
+--- a/gcc/config/arc/arc.h
++++ b/gcc/config/arc/arc.h
+@@ -674,6 +674,9 @@ enum reg_class
+    WRITABLE_CORE_REGS,		/* 'w' */
+    CHEAP_CORE_REGS,		/* 'c' */
+    ALL_CORE_REGS,		/* 'Rac' */
++   R0R3_CD_REGS,		/* 'Rcd' */
++   R0R1_CD_REGS,		/* 'Rsd' */
++   AC16_H_REGS,			/* 'h' */
+    ALL_REGS,
+    LIM_REG_CLASSES
+ };
+@@ -700,6 +703,9 @@ enum reg_class
+   "MPY_WRITABLE_CORE_REGS",   \
+   "WRITABLE_CORE_REGS",   \
+   "CHEAP_CORE_REGS",	  \
++  "R0R3_CD_REGS", \
++  "R0R1_CD_REGS", \
++  "AC16_H_REGS",	    \
+   "ALL_CORE_REGS",	  \
+   "ALL_REGS"          	  \
+ }
+@@ -732,6 +738,9 @@ enum reg_class
+   {0xffffffff, 0xd0000000, 0x00000000, 0x00000000, 0x00000000},      /* 'w', r0-r31, r60 */ \
+   {0xffffffff, 0xdfffffff, 0x00000000, 0x00000000, 0x00000000},      /* 'c', r0-r60, ap, pcl */ \
+   {0xffffffff, 0xdfffffff, 0x00000000, 0x00000000, 0x00000000},      /* 'Rac', r0-r60, ap, pcl */ \
++  {0x0000000f, 0x00000000, 0x00000000, 0x00000000, 0x00000000},      /* 'Rcd', r0-r3 */ \
++  {0x00000003, 0x00000000, 0x00000000, 0x00000000, 0x00000000},      /* 'Rsd', r0-r1 */ \
++  {0x9fffffff, 0x00000000, 0x00000000, 0x00000000, 0x00000000},      /* 'h',  r0-28, r30 */ \
+   {0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0x0003ffff}       /* All Registers */		\
+ }
+ 
+diff --git a/gcc/config/arc/arc.md b/gcc/config/arc/arc.md
+index c61107f4b416..85e54587d99d 100644
+--- a/gcc/config/arc/arc.md
++++ b/gcc/config/arc/arc.md
+@@ -620,14 +620,15 @@
+ ; The iscompact attribute allows the epilogue expander to know for which
+ ; insns it should lengthen the return insn.
+ (define_insn "*movqi_insn"
+-  [(set (match_operand:QI 0 "move_dest_operand" "=Rcq,Rcq#q,w,w,w,???w,w,Rcq,S,!*x,r,r,Ucm,m,???m")
+-	(match_operand:QI 1 "move_src_operand"  "cL,cP,Rcq#q,cL,I,?Rac,?i,T,Rcq,Usd,Ucm,m,?Rac,c,?Rac"))]
++  [(set (match_operand:QI 0 "move_dest_operand" "=Rcq,Rcq#q,    w,   h, w,w,???w, w,Rcq,  S,!*x,  r,r, Ucm,m,???m")
++	(match_operand:QI 1 "move_src_operand"  "  cL,   cP,Rcq#q,hCm1,cL,I,?Rac,?i,  T,Rcq,Usd,Ucm,m,?Rac,c,?Rac"))]
+   "register_operand (operands[0], QImode)
+    || register_operand (operands[1], QImode)"
+   "@
+    mov%? %0,%1%&
+    mov%? %0,%1%&
+    mov%? %0,%1%&
++   mov%? %0,%1%&
+    mov%? %0,%1
+    mov%? %0,%1
+    mov%? %0,%1
+@@ -640,10 +641,10 @@
+    xstb%U0 %1,%0
+    stb%U0%V0 %1,%0
+    stb%U0%V0 %1,%0"
+-  [(set_attr "type" "move,move,move,move,move,move,move,load,store,load,load,load,store,store,store")
+-   (set_attr "iscompact" "maybe,maybe,maybe,false,false,false,false,true,true,true,false,false,false,false,false")
+-   (set_attr "predicable" "yes,no,yes,yes,no,yes,yes,no,no,no,no,no,no,no,no")
+-   (set_attr "cpu_facility" "*,*,av1,*,*,*,*,*,*,*,*,*,*,*,*")])
++  [(set_attr "type" "move,move,move,move,move,move,move,move,load,store,load,load,load,store,store,store")
++   (set_attr "iscompact" "maybe,maybe,maybe,true,false,false,false,false,true,true,true,false,false,false,false,false")
++   (set_attr "predicable" "yes,no,yes,no,yes,no,yes,yes,no,no,no,no,no,no,no,no")
++   (set_attr "cpu_facility" "*,*,av1,av2,*,*,*,*,*,*,*,*,*,*,*,*")])
+ 
+ (define_expand "movhi"
+   [(set (match_operand:HI 0 "move_dest_operand" "")
+@@ -652,8 +653,8 @@
+   "if (prepare_move_operands (operands, HImode)) DONE;")
+ 
+ (define_insn "*movhi_insn"
+-  [(set (match_operand:HI 0 "move_dest_operand" "=Rcq,Rcq#q,w,w,w,???w,Rcq#q,w,Rcq,S,r,r,Ucm,m,???m,VUsc")
+-	(match_operand:HI 1 "move_src_operand" "cL,cP,Rcq#q,cL,I,?Rac,?i,?i,T,Rcq,Ucm,m,?Rac,c,?Rac,i"))]
++  [(set (match_operand:HI 0 "move_dest_operand" "=Rcq,Rcq#q,    w,   h, w,w,???w,Rcq#q, w,Rcq,  S,  r,r, Ucm,m,???m,VUsc,VUsc")
++	(match_operand:HI 1 "move_src_operand" "   cL,   cP,Rcq#q,hCm1,cL,I,?Rac,   ?i,?i,  T,Rcq,Ucm,m,?Rac,c,?Rac, Cm3,i"))]
+   "register_operand (operands[0], HImode)
+    || register_operand (operands[1], HImode)
+    || (CONSTANT_P (operands[1])
+@@ -665,6 +666,7 @@
+    mov%? %0,%1%&
+    mov%? %0,%1%&
+    mov%? %0,%1%&
++   mov%? %0,%1%&
+    mov%? %0,%1
+    mov%? %0,%1
+    mov%? %0,%1
+@@ -677,11 +679,12 @@
+    xst%_%U0 %1,%0
+    st%_%U0%V0 %1,%0
+    st%_%U0%V0 %1,%0
++   st%_%U0%V0 %S1,%0
+    st%_%U0%V0 %S1,%0"
+-  [(set_attr "type" "move,move,move,move,move,move,move,move,load,store,load,load,store,store,store,store")
+-   (set_attr "iscompact" "maybe,maybe,maybe,false,false,false,maybe_limm,false,true,true,false,false,false,false,false,false")
+-   (set_attr "predicable" "yes,no,yes,yes,no,yes,yes,yes,no,no,no,no,no,no,no,no")
+-   (set_attr "cpu_facility" "*,*,av1,*,*,*,*,*,*,*,*,*,*,*,*,*")])
++  [(set_attr "type" "move,move,move,move,move,move,move,move,move,load,store,load,load,store,store,store,store,store")
++   (set_attr "iscompact" "maybe,maybe,maybe,true,false,false,false,maybe_limm,false,true,true,false,false,false,false,false,false,false")
++   (set_attr "predicable" "yes,no,yes,no,yes,no,yes,yes,yes,no,no,no,no,no,no,no,no,no")
++   (set_attr "cpu_facility" "*,*,av1,av2,*,*,*,*,*,*,*,*,*,*,*,*,av2,*")])
+ 
+ (define_expand "movsi"
+   [(set (match_operand:SI 0 "move_dest_operand" "")
+@@ -699,9 +702,9 @@
+ ; the iscompact attribute allows the epilogue expander to know for which
+ ; insns it should lengthen the return insn.
+ ; N.B. operand 1 of alternative 7 expands into pcl,symbol at gotpc .
+-(define_insn "*movsi_insn"
+-  [(set (match_operand:SI 0 "move_dest_operand" "=Rcq,Rcq#q,w,w,w,w,w,w,w,???w,?w,w,Rcq#q,w,Rcq,S,Us<,RcqRck,!*x,r,r,Ucm,m,???m,VUsc")
+-	(match_operand:SI 1 "move_src_operand"  "cL,cP,Rcq#q,cL,I,Crr,Clo,Chi,Cbi,?Rac,Cpc,Clb,?Cal,?Cal,T,Rcq,RcqRck,Us>,Usd,Ucm,m,w,c,?Rac,C32"))]
++(define_insn "*movsi_insn"                      ;   0     1     2    3  4 5   6   7   8   9   10  11  12    13   14  15  16     17     18 19   20    21    22 23 24    25 26  27   28   29
++  [(set (match_operand:SI 0 "move_dest_operand" "=Rcq,Rcq#q,    w,   h, w,w,  w,  w,  w,  w,???w, ?w,  w,Rcq#q,   w,Rcq,  S,   Us<,RcqRck,!*x,  r,!*Rsd,!*Rcd,r,Ucm,  Usd,m,???m,VUsc,VUsc")
++	(match_operand:SI 1 "move_src_operand"  "  cL,   cP,Rcq#q,hCm1,cL,I,Crr,Clo,Chi,Cbi,?Rac,Cpc,Clb, ?Cal,?Cal,  T,Rcq,RcqRck,   Us>,Usd,Ucm,  Usd,  Ucd,m,  w,!*Rzd,c,?Rac, Cm3, C32"))]
+   "register_operand (operands[0], SImode)
+    || register_operand (operands[1], SImode)
+    || (CONSTANT_P (operands[1])
+@@ -713,35 +716,40 @@
+    mov%? %0,%1%&	;0
+    mov%? %0,%1%&	;1
+    mov%? %0,%1%&	;2
+-   mov%? %0,%1		;3
++   mov%? %0,%1%&	;3
+    mov%? %0,%1		;4
+-   ror %0,((%1*2+1) & 0x3f) ;5
+-   movl.cl %0,%1       ;6
+-   movh.cl %0,%L1>>16  ;7
++   mov%? %0,%1		;5
++   ror %0,((%1*2+1) & 0x3f) ;6
++   movl.cl %0,%1	;7
++   movh.cl %0,%L1>>16   ;8
+    * return INTVAL (operands[1]) & 0xffffff ? \"movbi.cl %0,%1 >> %p1,%p1,8;8\" : \"movbi.cl %0,%L1 >> 24,24,8;9\";
+-   mov%? %0,%1		;9
+-   add %0,%S1		;10
++   mov%? %0,%1		;10
++   add %0,%S1		;11
+    * return arc_get_unalign () ? \"add %0,pcl,%1-.+2\" : \"add %0,pcl,%1-.\";
+-   mov%? %0,%S1%&	;12
+-   mov%? %0,%S1		;13
+-   ld%? %0,%1%&		;14
+-   st%? %1,%0%&		;15
++   mov%? %0,%S1%&	;13
++   mov%? %0,%S1		;14
++   ld%? %0,%1%&		;15
++   st%? %1,%0%&		;16
+    * return arc_short_long (insn, \"push%? %1%&\", \"st%U0 %1,%0%&\");
+    * return arc_short_long (insn, \"pop%? %0%&\",  \"ld%U1 %0,%1%&\");
+-   ld%? %0,%1%&		;18
+-   xld%U1 %0,%1                ;19
+-   ld%U1%V1 %0,%1	;20
+-   xst%U0 %1,%0                ;21
+-   st%U0%V0 %1,%0       ;22
+-   st%U0%V0 %1,%0       ;23
+-   st%U0%V0 %S1,%0      ;24"
+-  [(set_attr "type" "move,move,move,move,move,two_cycle_core,shift,shift,shift,move,binary,binary,move,move,load,store,store,load,load,load,load,store,store,store,store")
+-   (set_attr "iscompact" "maybe,maybe,maybe,false,false,false,false,false,false,false,false,false,maybe_limm,false,true,true,true,true,true,false,false,false,false,false,false")
++   ld%? %0,%1%&		;19
++   xld%U1 %0,%1		;20
++   ld%? %0,%1%&		;21
++   ld%? %0,%1%&		;22
++   ld%U1%V1 %0,%1	;23
++   xst%U0 %1,%0		;24
++   st%? %1,%0%&		;25
++   st%U0%V0 %1,%0	;26
++   st%U0%V0 %1,%0	;27
++   st%U0%V0 %1,%0	;28
++   st%U0%V0 %S1,%0	;29"
++  [(set_attr "type" "move,move,move,move,move,move,two_cycle_core,shift,shift,shift,move,binary,binary,move,move,load,store,store,load,load,load,load,load,load,store,store,store,store,store,store")
++   (set_attr "iscompact" "maybe,maybe,maybe,false,false,false,false,false,false,false,false,false,maybe_limm,false,true,true,true,true,true,false,false,false,false,false,false,false,false,false,false,false")
+    ; Use default length for iscompact to allow for COND_EXEC.  But set length
+    ; of Crr to 4.
+-   (set_attr "length" "*,*,*,4,4,4,4,4,4,4,8,8,*,8,*,*,*,*,*,4,*,4,*,*,8")
+-   (set_attr "predicable" "yes,no,yes,yes,no,no,no,no,no,yes,no,no,yes,yes,no,no,no,no,no,no,no,no,no,no,no")
+-   (set_attr "cpu_facility" "*,*,av1,*,*,*,*,*,*,*,*,*,*,*,*,*,*,*,*,*,*,*,*,*,*")])
++   (set_attr "length" "*,*,*,*,4,4,4,4,4,4,4,8,8,*,8,*,*,*,*,*,4,*,4,*,*,*,*,*,4,8")
++   (set_attr "predicable" "yes,no,yes,no,yes,no,no,no,no,no,yes,no,no,yes,yes,no,no,no,no,no,no,no,no,no,no,no,no,no,no,no")
++   (set_attr "cpu_facility" "*,*,av1,av2,*,*,*,*,*,*,*,*,*,*,*,*,*,*,*,*,*,av2,av2,*,*,av2,*,*,av2,*")])
+ 
+ ;; Sometimes generated by the epilogue code.  We don't want to
+ ;; recognize these addresses in general, because the limm is costly,
+@@ -1136,17 +1144,19 @@
+   "if (prepare_move_operands (operands, SFmode)) DONE;")
+ 
+ (define_insn "*movsf_insn"
+-  [(set (match_operand:SF 0 "move_dest_operand" "=w,w,r,m")
+-	(match_operand:SF 1 "move_src_operand" "c,E,m,c"))]
++  [(set (match_operand:SF 0 "move_dest_operand"    "=h,w,w,r,m")
++	(match_operand:SF 1 "move_src_operand"   "hCm1,c,E,m,c"))]
+   "register_operand (operands[0], SFmode)
+    || register_operand (operands[1], SFmode)"
+   "@
+    mov%? %0,%1
++   mov%? %0,%1
+    mov%? %0,%1 ; %A1
+    ld%U1%V1 %0,%1
+    st%U0%V0 %1,%0"
+-  [(set_attr "type" "move,move,load,store")
+-   (set_attr "predicable" "yes,yes,no,no")])
++  [(set_attr "type" "move,move,move,load,store")
++   (set_attr "predicable" "no,yes,yes,no,no")
++   (set_attr "iscompact" "true,false,false,false,false")])
+ 
+ (define_expand "movdf"
+   [(set (match_operand:DF 0 "nonimmediate_operand" "")
+@@ -1664,17 +1674,18 @@
+ )
+ 
+ (define_insn "*extendhisi2_i"
+-  [(set (match_operand:SI 0 "dest_reg_operand" "=Rcqq,w,r,r")
+-	(sign_extend:SI (match_operand:HI 1 "nonvol_nonimm_operand" "Rcqq,c,Uex,m")))]
++  [(set (match_operand:SI 0 "dest_reg_operand" "=Rcqq,w,Rcq,r,r")
++	(sign_extend:SI (match_operand:HI 1 "nonvol_nonimm_operand" "Rcqq,c,Ucd,Uex,m")))]
+   ""
+   "@
+    sex%_%? %0,%1%&
+    sex%_ %0,%1
++   ldh%?.x %0,%1%&
+    ld%_.x%U1%V1 %0,%1
+    ld%_.x%U1%V1 %0,%1"
+-  [(set_attr "type" "unary,unary,load,load")
+-   (set_attr "iscompact" "true,false,false,false")
+-   (set_attr "length" "*,*,4,8")])
++  [(set_attr "type" "unary,unary,load,load,load")
++   (set_attr "iscompact" "true,false,true,false,false")
++   (set_attr "length" "*,*,*,4,8")])
+ 
+ (define_expand "extendhisi2"
+   [(set (match_operand:SI 0 "dest_reg_operand" "")
+@@ -3041,9 +3052,9 @@
+      operands[1] = arc_rewrite_small_data (operands[1]);")
+ 
+ (define_insn "andsi3_i"
+-  [(set (match_operand:SI 0 "dest_reg_operand" "=Rcqq,Rcq,Rcqq,Rcqq,Rcqq,Rcw,Rcw,Rcw,Rcw,Rcw,Rcw,w,w,w,w,Rrq,w,Rcw,w,W")
+-	(and:SI (match_operand:SI 1 "nonimmediate_operand" "%0,Rcq,0,0,Rcqq,0,c,0,0,0,0,c,c,c,c,Rrq,0,0,c,o")
+-		(match_operand:SI 2 "nonmemory_operand" "Rcqq,0,C1p,Ccp,Cux,cL,0,C1p,Ccp,CnL,I,Lc,C1p,Ccp,CnL,Cbf,I,Cal,Cal,Cux")))]
++  [(set (match_operand:SI 0 "dest_reg_operand"          "=Rcqq,Rcq,Rcqq,Rcqq,Rcqq,Rcw,Rcw,   Rcw,Rcw,Rcw,Rcw, w,     w,  w,  w,Rrq,w,Rcw,  w,W")
++	(and:SI (match_operand:SI 1 "nonimmediate_operand" "%0,Rcq,   0,   0,Rcqq,  0,  c,     0,  0,  0,  0, c,     c,  c,  c,Rrq,0,  0,  c,o")
++		(match_operand:SI 2 "nonmemory_operand"  "Rcqq,  0, C1p, Ccp, Cux, cL,  0,C2pC1p,Ccp,CnL,  I,Lc,C2pC1p,Ccp,CnL,Cbf,I,Cal,Cal,Cux")))]
+   "(register_operand (operands[1], SImode)
+     && nonmemory_operand (operands[2], SImode))
+    || (memory_operand (operands[1], SImode)
+@@ -3055,8 +3066,18 @@
+       return "and%? %0,%1,%2%&";
+     case 1: case 6:
+       return "and%? %0,%2,%1%&";
+-    case 2: case 7: case 12:
++    case 2:
+       return "bmsk%? %0,%1,%Z2%&";
++    case 7: case 12:
++     if (satisfies_constraint_C2p (operands[2]))
++       {
++	operands[2] = GEN_INT ((~INTVAL (operands[2])));
++	return "bmskn%? %0,%1,%Z2%&";
++       }
++     else
++       {
++	return "bmsk%? %0,%1,%Z2%&";
++       }
+     case 3: case 8: case 13:
+       return "bclr%? %0,%1,%M2%&";
+     case 4:
+@@ -3368,15 +3389,15 @@
+ ;; modifed cc user if second, but not first operand is a compact register.
+ (define_insn "cmpsi_cc_insn_mixed"
+   [(set (reg:CC CC_REG)
+-	(compare:CC (match_operand:SI 0 "register_operand" "Rcq#q,c,c, qRcq, c")
+-		    (match_operand:SI 1 "nonmemory_operand" "cO,cI,cL,  Cal, Cal")))]
++	(compare:CC (match_operand:SI 0 "register_operand" "Rcq#q,  h, c, c,qRcq,c")
++		    (match_operand:SI 1 "nonmemory_operand"   "cO,Cm1,cI,cL, Cal,Cal")))]
+   ""
+   "cmp%? %0,%B1%&"
+   [(set_attr "type" "compare")
+-   (set_attr "iscompact" "true,false,false,true_limm,false")
+-   (set_attr "predicable" "no,no,yes,no,yes")
++   (set_attr "iscompact" "true,true,false,false,true_limm,false")
++   (set_attr "predicable" "no,no,no,yes,no,yes")
+    (set_attr "cond" "set")
+-   (set_attr "length" "*,4,4,*,8")])
++   (set_attr "length" "*,*,4,4,*,8")])
+ 
+ (define_insn "*cmpsi_cc_zn_insn"
+   [(set (reg:CC_ZN CC_REG)
+@@ -3452,14 +3473,14 @@
+ 
+ (define_insn "*cmpsi_cc_c_insn"
+   [(set (reg:CC_C CC_REG)
+-	(compare:CC_C (match_operand:SI 0 "register_operand"  "Rcqq, c,Rcqq,  c")
+-		      (match_operand:SI 1 "nonmemory_operand" "cO,  cI, Cal,Cal")))]
++	(compare:CC_C (match_operand:SI 0 "register_operand"  "Rcqq,  h, c,Rcqq,  c")
++		      (match_operand:SI 1 "nonmemory_operand"   "cO,Cm1,cI, Cal,Cal")))]
+   ""
+   "cmp%? %0,%S1%&"
+   [(set_attr "type" "compare")
+-   (set_attr "iscompact" "true,false,true_limm,false")
++   (set_attr "iscompact" "true,true,false,true_limm,false")
+    (set_attr "cond" "set")
+-   (set_attr "length" "*,4,*,8")])
++   (set_attr "length" "*,*,4,*,8")])
+ 
+ ;; Next come the scc insns.
+ 
+@@ -3552,17 +3573,20 @@
+ ; cond_exec patterns
+ (define_insn "*movsi_ne"
+   [(cond_exec
+-     (ne (match_operand:CC_Z 2 "cc_use_register" "Rcc,Rcc,Rcc") (const_int 0))
+-     (set (match_operand:SI 0 "dest_reg_operand" "=Rcq#q,w,w")
+-	  (match_operand:SI 1 "nonmemory_operand" "C_0,Lc,?Cal")))]
++     (ne (match_operand:CC_Z 2 "cc_use_register"    "Rcc,  Rcc,  Rcc,Rcc,Rcc") (const_int 0))
++     (set (match_operand:SI 0 "dest_reg_operand" "=Rcq#q,Rcq#q,Rcq#q,  w,w")
++	  (match_operand:SI 1 "nonmemory_operand"   "C_0,    h, ?Cal, Lc,?Cal")))]
+   ""
+   "@
+ 	* current_insn_predicate = 0; return \"sub%?.ne %0,%0,%0%&\";
++	* current_insn_predicate = 0; return \"mov%?.ne %0,%1\";
++	* current_insn_predicate = 0; return \"mov%?.ne %0,%1\";
+ 	mov.ne %0,%1
+ 	mov.ne %0,%S1"
+-  [(set_attr "type" "cmove,cmove,cmove")
+-   (set_attr "iscompact" "true,false,false")
+-   (set_attr "length" "2,4,8")])
++  [(set_attr "type" "cmove")
++   (set_attr "iscompact" "true,true,true_limm,false,false")
++   (set_attr "length" "2,2,6,4,8")
++   (set_attr "cpu_facility" "*,av2,av2,*,*")])
+ 
+ (define_insn "*movsi_cond_exec"
+   [(cond_exec
+diff --git a/gcc/config/arc/constraints.md b/gcc/config/arc/constraints.md
+index 5069d7d9746d..b7bf2d39c4e8 100644
+--- a/gcc/config/arc/constraints.md
++++ b/gcc/config/arc/constraints.md
+@@ -226,6 +226,14 @@
+   (and (match_code "const_int")
+        (match_test "ival && IS_POWEROF2_P (ival + 1)")))
+ 
++(define_constraint "C2p"
++ "@internal
++  constant such that (~x)+1 is a power of two, and x < -1"
++  (and (match_code "const_int")
++       (match_test "TARGET_V2
++		    && (ival < -1)
++		    && IS_POWEROF2_P ((~ival) + 1)")))
++
+ (define_constraint "C3p"
+  "@internal
+   constant int used to select xbfu a,b,u6 instruction.  The values accepted are 1 and 2."
+@@ -317,7 +325,13 @@
+   "@internal
+    A valid memory operand for ARCompact load instructions"
+   (and (match_code "mem")
+-       (match_test "compact_load_memory_operand (op, VOIDmode)")))
++       (match_test "compact_memory_operand_p (op, mode, false, false)")))
++
++(define_memory_constraint "Uts"
++  "@internal
++   A valid memory operand for ARCompact load instructions scaled"
++  (and (match_code "mem")
++       (match_test "compact_memory_operand_p (op, mode, false, TARGET_CODE_DENSITY)")))
+ 
+ (define_memory_constraint "S"
+   "@internal
+@@ -340,7 +354,7 @@
+    "@internal
+     A valid _small-data_ memory operand for ARCompact instructions"
+    (and (match_code "mem")
+-        (match_test "compact_sda_memory_operand (op, VOIDmode)")))
++	(match_test "compact_sda_memory_operand (op, VOIDmode)")))
+ 
+ (define_memory_constraint "Usc"
+   "@internal
+@@ -483,12 +497,26 @@
+   (and (match_code "const_int")
+        (match_test "IS_ZERO (ival)")))
+ 
++(define_constraint "Cm1"
++  "@internal
++   Integer signed constant in the interval [-1,6]"
++  (and (match_code "const_int")
++       (match_test "(ival >= -1) && (ival <=6)")
++       (match_test "TARGET_V2")))
++
+ (define_constraint "Cm2"
+   "@internal
+    A signed 9-bit integer constant."
+   (and (match_code "const_int")
+        (match_test "(ival >= -256) && (ival <=255)")))
+ 
++(define_constraint "Cm3"
++  "@internal
++   A signed 6-bit integer constant."
++  (and (match_code "const_int")
++       (match_test "(ival >= -32) && (ival <=31)")
++       (match_test "TARGET_V2")))
++
+ (define_constraint "C62"
+   "@internal
+    An unsigned 6-bit integer constant, up to 62."
+@@ -511,3 +539,32 @@
+    An unsigned 16-bit integer constant"
+   (and (match_code "const_int")
+        (match_test "UNSIGNED_INT16 (ival)")))
++
++; Memory addresses suited for code density load ops
++(define_memory_constraint "Ucd"
++  "@internal
++   A valid memory operand for use with code density load ops"
++  (and (match_code "mem")
++       (match_test "compact_memory_operand_p (op, mode, true, false)")
++       (match_test "TARGET_V2")))
++
++(define_register_constraint "h"
++  "TARGET_V2 ? AC16_H_REGS : NO_REGS"
++  "5-bit h register set except @code{r30} and @code{r29}:
++   @code{r0}- at code{r31}, nonfixed core register")
++
++; Code density registers
++(define_register_constraint "Rcd"
++  "TARGET_CODE_DENSITY ? R0R3_CD_REGS : NO_REGS"
++  "@internal
++   core register @code{r0}- at code{r3}")
++
++(define_register_constraint "Rsd"
++  "TARGET_CODE_DENSITY ? R0R1_CD_REGS : NO_REGS"
++  "@internal
++   core register @code{r0}- at code{r1}")
++
++(define_register_constraint "Rzd"
++  "TARGET_CODE_DENSITY ? R0_REGS : NO_REGS"
++  "@internal
++   @code{r0} register for code density instructions.")
+diff --git a/gcc/config/arc/predicates.md b/gcc/config/arc/predicates.md
+index 8e4b4b40c543..f85f931d4601 100644
+--- a/gcc/config/arc/predicates.md
++++ b/gcc/config/arc/predicates.md
+@@ -185,95 +185,6 @@
+ )
+ 
+ ;; Return true if OP is an acceptable memory operand for ARCompact
+-;; 16-bit load instructions.
+-(define_predicate "compact_load_memory_operand"
+-  (match_code "mem")
+-{
+-  rtx addr, plus0, plus1;
+-  int size, off;
+-
+-  /* Eliminate non-memory operations.  */
+-  if (GET_CODE (op) != MEM)
+-    return 0;
+-
+-  /* .di instructions have no 16-bit form.  */
+-  if (MEM_VOLATILE_P (op) && !TARGET_VOLATILE_CACHE_SET)
+-     return 0;
+-
+-  if (mode == VOIDmode)
+-    mode = GET_MODE (op);
+-
+-  size = GET_MODE_SIZE (mode);
+-
+-  /* dword operations really put out 2 instructions, so eliminate them.  */
+-  if (size > UNITS_PER_WORD)
+-    return 0;
+-
+-  /* Decode the address now.  */
+-  addr = XEXP (op, 0);
+-  switch (GET_CODE (addr))
+-    {
+-    case REG:
+-      return (REGNO (addr) >= FIRST_PSEUDO_REGISTER
+-	      || COMPACT_GP_REG_P (REGNO (addr))
+-	      || (SP_REG_P (REGNO (addr)) && (size != 2)));
+-	/* Reverting for the moment since ldw_s does not have sp as a valid
+-	   parameter.  */
+-    case PLUS:
+-      plus0 = XEXP (addr, 0);
+-      plus1 = XEXP (addr, 1);
+-
+-      if ((GET_CODE (plus0) == REG)
+-	  && ((REGNO (plus0) >= FIRST_PSEUDO_REGISTER)
+-	      || COMPACT_GP_REG_P (REGNO (plus0)))
+-	  && ((GET_CODE (plus1) == REG)
+-	      && ((REGNO (plus1) >= FIRST_PSEUDO_REGISTER)
+-		  || COMPACT_GP_REG_P (REGNO (plus1)))))
+-	{
+-	  return 1;
+-	}
+-
+-      if ((GET_CODE (plus0) == REG)
+-	  && ((REGNO (plus0) >= FIRST_PSEUDO_REGISTER)
+-	      || COMPACT_GP_REG_P (REGNO (plus0)))
+-	  && (GET_CODE (plus1) == CONST_INT))
+-	{
+-	  off = INTVAL (plus1);
+-
+-	  /* Negative offset is not supported in 16-bit load/store insns.  */
+-	  if (off < 0)
+-	    return 0;
+-
+-	  switch (size)
+-	    {
+-	    case 1:
+-	      return (off < 32);
+-	    case 2:
+-	      return ((off < 64) && (off % 2 == 0));
+-	    case 4:
+-	      return ((off < 128) && (off % 4 == 0));
+-	    }
+-	}
+-
+-      if ((GET_CODE (plus0) == REG)
+-	  && ((REGNO (plus0) >= FIRST_PSEUDO_REGISTER)
+-	      || SP_REG_P (REGNO (plus0)))
+-	  && (GET_CODE (plus1) == CONST_INT))
+-	{
+-	  off = INTVAL (plus1);
+-	  return ((size != 2) && (off >= 0 && off < 128) && (off % 4 == 0));
+-	}
+-    default:
+-      break ;
+-      /* TODO: 'gp' and 'pcl' are to supported as base address operand
+-	       for 16-bit load instructions.  */
+-    }
+-  return 0;
+-
+-}
+-)
+-
+-;; Return true if OP is an acceptable memory operand for ARCompact
+ ;; 16-bit store instructions
+ (define_predicate "compact_store_memory_operand"
+   (match_code "mem")
+-- 
+2.7.4
+
diff --git a/toolchain/gcc/patches/6.3.0/0018-Fix-warnings-update-source-code.patch b/toolchain/gcc/patches/6.3.0/0018-Fix-warnings-update-source-code.patch
new file mode 100644
index 0000000..f10dd45
--- /dev/null
+++ b/toolchain/gcc/patches/6.3.0/0018-Fix-warnings-update-source-code.patch
@@ -0,0 +1,80 @@
+From fab0b35c130abbd2ef3bbf020a443bbbd5d833a7 Mon Sep 17 00:00:00 2001
+From: claziss <claziss at 138bc75d-0d04-0410-961f-82ee72b054a4>
+Date: Mon, 2 May 2016 09:37:17 +0000
+Subject: [PATCH 18/89] Fix warnings, update source code.
+
+include/
+2016-05-02  Claudiu Zissulescu  <claziss at synopsys.com>
+
+	* config/arc/arc.c (arc_preferred_simd_mode): Remove enum keyword.
+	(arc_save_restore): Likewise.
+	(arc_dwarf_register_span): Likewise.
+	(arc_output_pic_addr_const): Initialize suffix variable.
+
+git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@235718 138bc75d-0d04-0410-961f-82ee72b054a4
+---
+ gcc/ChangeLog        | 7 +++++++
+ gcc/config/arc/arc.c | 9 +++++----
+ 2 files changed, 12 insertions(+), 4 deletions(-)
+
+diff --git a/gcc/ChangeLog b/gcc/ChangeLog
+index cedbe6eb44f2..4d6016b6cbe6 100644
+--- a/gcc/ChangeLog
++++ b/gcc/ChangeLog
+@@ -1,5 +1,12 @@
+ 2016-05-02  Claudiu Zissulescu  <claziss at synopsys.com>
+ 
++	* config/arc/arc.c (arc_preferred_simd_mode): Remove enum keyword.
++	(arc_save_restore): Likewise.
++	(arc_dwarf_register_span): Likewise.
++	(arc_output_pic_addr_const): Initialize suffix variable.
++
++2016-05-02  Claudiu Zissulescu  <claziss at synopsys.com>
++
+ 	* config/arc/arc-protos.h (compact_memory_operand_p): Declare.
+ 	* config/arc/arc.c (arc_output_commutative_cond_exec): Consider
+ 	bmaskn instruction.
+diff --git a/gcc/config/arc/arc.c b/gcc/config/arc/arc.c
+index a54fddb45d32..49edc0a7f657 100644
+--- a/gcc/config/arc/arc.c
++++ b/gcc/config/arc/arc.c
+@@ -264,8 +264,8 @@ arc_vector_mode_supported_p (machine_mode mode)
+ 
+ /* Implements target hook TARGET_VECTORIZE_PREFERRED_SIMD_MODE.  */
+ 
+-static enum machine_mode
+-arc_preferred_simd_mode (enum machine_mode mode)
++static machine_mode
++arc_preferred_simd_mode (machine_mode mode)
+ {
+   switch (mode)
+     {
+@@ -2347,7 +2347,7 @@ arc_save_restore (rtx base_reg,
+ 
+       for (regno = 0; regno <= 31; regno++)
+ 	{
+-	  enum machine_mode mode = SImode;
++	  machine_mode mode = SImode;
+ 	  bool found = false;
+ 
+ 	  if (TARGET_LL64
+@@ -5124,6 +5124,7 @@ arc_output_pic_addr_const (FILE * file, rtx x, int code)
+ 	    suffix = "@dtpoff";
+ 	  break;
+ 	default:
++	  suffix = "@invalid";
+ 	  output_operand_lossage ("invalid UNSPEC as operand: %d", XINT (x,1));
+ 	  break;
+ 	}
+@@ -9847,7 +9848,7 @@ arc_no_speculation_in_delay_slots_p ()
+ static rtx
+ arc_dwarf_register_span (rtx rtl)
+ {
+-   enum machine_mode mode = GET_MODE (rtl);
++   machine_mode mode = GET_MODE (rtl);
+    unsigned regno;
+    rtx p;
+ 
+-- 
+2.7.4
+
diff --git a/toolchain/gcc/patches/6.3.0/0019-ARC-Various-instruction-pattern-fixes.patch b/toolchain/gcc/patches/6.3.0/0019-ARC-Various-instruction-pattern-fixes.patch
new file mode 100644
index 0000000..af5d6fc
--- /dev/null
+++ b/toolchain/gcc/patches/6.3.0/0019-ARC-Various-instruction-pattern-fixes.patch
@@ -0,0 +1,83 @@
+From 1efcfe036db8f976fe65af2c1c7bcfadc5ba6cbf Mon Sep 17 00:00:00 2001
+From: claziss <claziss at 138bc75d-0d04-0410-961f-82ee72b054a4>
+Date: Mon, 2 May 2016 11:26:57 +0000
+Subject: [PATCH 19/89] [ARC] Various instruction pattern fixes
+
+gcc/
+2016-05-02  Claudiu Zissulescu  <claziss at synopsys.com>
+
+	* config/arc/arc.md (mulsidi3): Change operand 0 predicate to
+	register_operand.
+	(umulsidi3): Likewise.
+	(indirect_jump): Fix jump instruction assembly patterns.
+
+git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@235749 138bc75d-0d04-0410-961f-82ee72b054a4
+---
+ gcc/ChangeLog         |  7 +++++++
+ gcc/config/arc/arc.md | 19 ++++++++++++-------
+ 2 files changed, 19 insertions(+), 7 deletions(-)
+
+diff --git a/gcc/ChangeLog b/gcc/ChangeLog
+index 4d6016b6cbe6..bfda3c16668f 100644
+--- a/gcc/ChangeLog
++++ b/gcc/ChangeLog
+@@ -1,5 +1,12 @@
+ 2016-05-02  Claudiu Zissulescu  <claziss at synopsys.com>
+ 
++	* config/arc/arc.md (mulsidi3): Change operand 0 predicate to
++	register_operand.
++	(umulsidi3): Likewise.
++	(indirect_jump): Fix jump instruction assembly patterns.
++
++2016-05-02  Claudiu Zissulescu  <claziss at synopsys.com>
++
+ 	* config/arc/arc.c (arc_preferred_simd_mode): Remove enum keyword.
+ 	(arc_save_restore): Likewise.
+ 	(arc_dwarf_register_span): Likewise.
+diff --git a/gcc/config/arc/arc.md b/gcc/config/arc/arc.md
+index 85e54587d99d..a4ee08450a8c 100644
+--- a/gcc/config/arc/arc.md
++++ b/gcc/config/arc/arc.md
+@@ -2079,9 +2079,9 @@
+   (set_attr "cond" "nocond,canuse,nocond,canuse_limm,canuse,nocond")])
+ 
+ (define_expand "mulsidi3"
+-  [(set (match_operand:DI 0 "nonimmediate_operand" "")
+-	(mult:DI (sign_extend:DI(match_operand:SI 1 "register_operand" ""))
+-		 (sign_extend:DI(match_operand:SI 2 "nonmemory_operand" ""))))]
++  [(set (match_operand:DI 0 "register_operand" "")
++	(mult:DI (sign_extend:DI (match_operand:SI 1 "register_operand" ""))
++		 (sign_extend:DI (match_operand:SI 2 "nonmemory_operand" ""))))]
+   "TARGET_ANY_MPY"
+ "
+ {
+@@ -2315,9 +2315,9 @@
+ }")
+ 
+ (define_expand "umulsidi3"
+-  [(set (match_operand:DI 0 "nonimmediate_operand" "")
+-	(mult:DI (zero_extend:DI(match_operand:SI 1 "register_operand" ""))
+-		 (zero_extend:DI(match_operand:SI 2 "nonmemory_operand" ""))))]
++  [(set (match_operand:DI 0 "register_operand" "")
++	(mult:DI (zero_extend:DI (match_operand:SI 1 "register_operand" ""))
++		 (zero_extend:DI (match_operand:SI 2 "nonmemory_operand" ""))))]
+   ""
+ {
+   if (TARGET_MPY)
+@@ -3809,7 +3809,12 @@
+ (define_insn "indirect_jump"
+   [(set (pc) (match_operand:SI 0 "nonmemory_operand" "L,I,Cal,Rcqq,r"))]
+   ""
+-  "j%!%* [%0]%&"
++  "@
++   j%!%* %0%&
++   j%!%* %0%&
++   j%!%* %0%&
++   j%!%* [%0]%&
++   j%!%* [%0]%&"
+   [(set_attr "type" "jump")
+    (set_attr "iscompact" "false,false,false,maybe,false")
+    (set_attr "cond" "canuse,canuse_limm,canuse,canuse,canuse")])
+-- 
+2.7.4
+
diff --git a/toolchain/gcc/patches/6.3.0/0020-ARC-New-CPU-C-define-handler.patch b/toolchain/gcc/patches/6.3.0/0020-ARC-New-CPU-C-define-handler.patch
new file mode 100644
index 0000000..f02c5d0
--- /dev/null
+++ b/toolchain/gcc/patches/6.3.0/0020-ARC-New-CPU-C-define-handler.patch
@@ -0,0 +1,303 @@
+From 47b0081d32fea4a2bdae217281244146133d18c2 Mon Sep 17 00:00:00 2001
+From: Claudiu Zissulescu <claziss at synopsys.com>
+Date: Tue, 3 May 2016 11:50:42 +0200
+Subject: [PATCH 20/89] [ARC] New CPU C-define handler.
+
+gcc/
+2016-05-02  Claudiu Zissulescu  <claziss at synopsys.com>
+
+	* config/arc/arc-c.c: New file.
+	* config/arc/arc-c.def: Likewise.
+	* config/arc/t-arc: Likewise.
+	* config.gcc: Include arc-c.o as c and cpp object.
+	* config/arc/arc-protos.h (arc_cpu_cpp_builtins): Add prototype.
+	* config/arc/arc.h (TARGET_CPU_CPP_BUILTINS): Use
+	arc_cpu_cpp_builtins.
+---
+ gcc/config.gcc              |  2 ++
+ gcc/config/arc/arc-c.c      | 69 +++++++++++++++++++++++++++++++++++++++++++++
+ gcc/config/arc/arc-c.def    | 68 ++++++++++++++++++++++++++++++++++++++++++++
+ gcc/config/arc/arc-protos.h |  1 +
+ gcc/config/arc/arc.h        | 56 +-----------------------------------
+ gcc/config/arc/t-arc        | 29 +++++++++++++++++++
+ 6 files changed, 170 insertions(+), 55 deletions(-)
+ create mode 100644 gcc/config/arc/arc-c.c
+ create mode 100644 gcc/config/arc/arc-c.def
+ create mode 100644 gcc/config/arc/t-arc
+
+diff --git a/gcc/config.gcc b/gcc/config.gcc
+index 1d5b23f228d2..2cc649e1dc83 100644
+--- a/gcc/config.gcc
++++ b/gcc/config.gcc
+@@ -323,6 +323,8 @@ am33_2.0-*-linux*)
+ 	;;
+ arc*-*-*)
+ 	cpu_type=arc
++	c_target_objs="arc-c.o"
++	cxx_target_objs="arc-c.o"
+ 	;;
+ arm*-*-*)
+ 	cpu_type=arm
+diff --git a/gcc/config/arc/arc-c.c b/gcc/config/arc/arc-c.c
+new file mode 100644
+index 000000000000..3bf3fd26c2c4
+--- /dev/null
++++ b/gcc/config/arc/arc-c.c
+@@ -0,0 +1,69 @@
++/* Copyright (C) 2016 Free Software Foundation, Inc.
++
++   This file is part of GCC.
++
++   GCC is free software; you can redistribute it and/or modify it
++   under the terms of the GNU General Public License as published by
++   the Free Software Foundation; either version 3, or (at your option)
++   any later version.
++
++   GCC is distributed in the hope that it will be useful, but WITHOUT
++   ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
++   or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public
++   License for more details.
++
++   You should have received a copy of the GNU General Public License
++   along with GCC; see the file COPYING3.  If not see
++   <http://www.gnu.org/licenses/>.
++*/
++
++#include "config.h"
++#include "system.h"
++#include "coretypes.h"
++#include "tm.h"
++#include "tree.h"
++#include "tm_p.h"
++#include "cpplib.h"
++#include "c-family/c-common.h"
++#include "target.h"
++
++#define builtin_define(TXT) cpp_define (pfile, TXT)
++#define builtin_assert(TXT) cpp_assert (pfile, TXT)
++
++/* Define or undefine macros based on the current target.  */
++
++static void
++def_or_undef_macro (cpp_reader* pfile, const char *name, bool def_p)
++{
++  if (def_p)
++    cpp_define (pfile, name);
++  else
++    cpp_undef (pfile, name);
++}
++
++/* Helper for TARGET_CPU_CPP_BUILTINS hook.  */
++
++void
++arc_cpu_cpp_builtins (cpp_reader * pfile)
++{
++  builtin_assert ("cpu=arc");
++  builtin_assert ("machine=arc");
++
++  builtin_define ("__arc__");
++
++#undef ARC_C_DEF
++#define ARC_C_DEF(NAME, CONDITION)		\
++  def_or_undef_macro (pfile, NAME, CONDITION);
++
++#include "arc-c.def"
++#undef ARC_C_DEF
++
++  builtin_define_with_int_value ("__ARC_TLS_REGNO__",
++				 arc_tp_regno);
++
++  builtin_define (TARGET_BIG_ENDIAN
++		  ? "__BIG_ENDIAN__" : "__LITTLE_ENDIAN__");
++  if (TARGET_BIG_ENDIAN)
++    builtin_define ("__big_endian__");
++
++}
+diff --git a/gcc/config/arc/arc-c.def b/gcc/config/arc/arc-c.def
+new file mode 100644
+index 000000000000..065e97360ded
+--- /dev/null
++++ b/gcc/config/arc/arc-c.def
+@@ -0,0 +1,68 @@
++/* Copyright (C) 2016 Free Software Foundation, Inc.
++
++   This file is part of GCC.
++
++   GCC is free software; you can redistribute it and/or modify it
++   under the terms of the GNU General Public License as published by
++   the Free Software Foundation; either version 3, or (at your option)
++   any later version.
++
++   GCC is distributed in the hope that it will be useful, but WITHOUT
++   ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
++   or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public
++   License for more details.
++
++   You should have received a copy of the GNU General Public License
++   along with GCC; see the file COPYING3.  If not see
++   <http://www.gnu.org/licenses/>.
++*/
++
++ARC_C_DEF ("__ARC600__",	TARGET_ARC600)
++ARC_C_DEF ("__ARC601__",	TARGET_ARC601)
++ARC_C_DEF ("__ARC700__",	TARGET_ARC700)
++ARC_C_DEF ("__ARCEM__",		TARGET_EM)
++ARC_C_DEF ("__ARCHS__",		TARGET_HS)
++ARC_C_DEF ("__ARC_ATOMIC__",	TARGET_ATOMIC)
++ARC_C_DEF ("__ARC_NORM__",	TARGET_NORM)
++ARC_C_DEF ("__ARC_MUL64__",	TARGET_MUL64_SET)
++ARC_C_DEF ("__ARC_MUL32BY16__", TARGET_MULMAC_32BY16_SET)
++ARC_C_DEF ("__ARC_SIMD__",	TARGET_SIMD_SET)
++
++ARC_C_DEF ("__ARC_BARREL_SHIFTER__", TARGET_BARREL_SHIFTER)
++
++ARC_C_DEF ("__ARC_LL64__",   TARGET_LL64)
++ARC_C_DEF ("__ARC_MPY__",    TARGET_MPY)
++ARC_C_DEF ("__ARC_SWAP__",   TARGET_SWAP)
++ARC_C_DEF ("__ARC_EA__",     TARGET_EA_SET)
++ARC_C_DEF ("__ARC_FPX_SP__", (TARGET_SPFP_FAST_SET || TARGET_SPFP_COMPACT_SET))
++ARC_C_DEF ("__ARC_FPX_DP__", (TARGET_DPFP_FAST_SET || TARGET_DPFP_COMPACT_SET))
++ARC_C_DEF ("__ARC_MULT32__", TARGET_MUL64_SET)
++ARC_C_DEF ("__ARC_DIVREM__", TARGET_DIVREM)
++
++ARC_C_DEF ("__ARC_CODE_DENSITY__", TARGET_CODE_DENSITY)
++
++ARC_C_DEF ("__ARC_MPY_WLHX__",   (arc_mpy_option >= 2))
++ARC_C_DEF ("__ARC_MPY_WLH1__",   (arc_mpy_option == 2))
++ARC_C_DEF ("__ARC_MPY_WLH2__",   (arc_mpy_option == 3))
++ARC_C_DEF ("__ARC_MPY_WLH3__",   (arc_mpy_option == 4))
++ARC_C_DEF ("__ARC_MPY_WLH4__",   (arc_mpy_option == 5))
++ARC_C_DEF ("__ARC_MPY_WLH5__",   (arc_mpy_option == 6))
++ARC_C_DEF ("__ARC_MPY_DMPY__",   (arc_mpy_option == 7))
++ARC_C_DEF ("__ARC_MPY_MACD__",   (arc_mpy_option == 8))
++ARC_C_DEF ("__ARC_MPY_QMACW__",  (arc_mpy_option == 9))
++
++ARC_C_DEF ("__ARC_FPU_SP__",     TARGET_FP_SP_BASE)
++ARC_C_DEF ("__ARC_FPU_DP__",     TARGET_FP_DP_BASE)
++ARC_C_DEF ("__ARC_FPU_SP_DIV__", TARGET_FP_SP_SQRT)
++ARC_C_DEF ("__ARC_FPU_DP_DIV__", TARGET_FP_DP_SQRT)
++ARC_C_DEF ("__ARC_FPU_SP_FMA__", TARGET_FP_SP_FUSED)
++ARC_C_DEF ("__ARC_FPU_DP_FMA__", TARGET_FP_DP_FUSED)
++ARC_C_DEF ("__ARC_FPU_ASSIST__", TARGET_FP_DP_AX)
++
++/* To be deprecated.  */
++ARC_C_DEF ("__A6__",     TARGET_ARC600)
++ARC_C_DEF ("__A7__",     TARGET_ARC700)
++ARC_C_DEF ("__EM__",     TARGET_EM)
++ARC_C_DEF ("__HS__",     TARGET_HS)
++ARC_C_DEF ("__Xnorm",    TARGET_NORM)
++ARC_C_DEF ("__Xbarrel_shifter", TARGET_BARREL_SHIFTER)
+diff --git a/gcc/config/arc/arc-protos.h b/gcc/config/arc/arc-protos.h
+index 8630e2d84daa..b6ed39268c25 100644
+--- a/gcc/config/arc/arc-protos.h
++++ b/gcc/config/arc/arc-protos.h
+@@ -123,3 +123,4 @@ extern int arc_return_slot_offset (void);
+ extern bool arc_legitimize_reload_address (rtx *, machine_mode, int, int);
+ extern void arc_secondary_reload_conv (rtx, rtx, rtx, bool);
+ extern bool insn_is_tls_gd_dispatch (rtx_insn *);
++extern void arc_cpu_cpp_builtins (cpp_reader *);
+diff --git a/gcc/config/arc/arc.h b/gcc/config/arc/arc.h
+index f6b85ea7e51b..c02e1cd4c777 100644
+--- a/gcc/config/arc/arc.h
++++ b/gcc/config/arc/arc.h
+@@ -64,61 +64,7 @@ along with GCC; see the file COPYING3.  If not see
+ #undef CC1_SPEC
+ 
+ /* Names to predefine in the preprocessor for this target machine.  */
+-#define TARGET_CPU_CPP_BUILTINS()	\
+- do {					\
+-    builtin_define ("__arc__");		\
+-    if (TARGET_ARC600)			\
+-      {					\
+-	builtin_define ("__A6__");	\
+-	builtin_define ("__ARC600__");	\
+-      }					\
+-    else if (TARGET_ARC601)			\
+-      {					\
+-	builtin_define ("__ARC601__");	\
+-      }					\
+-    else if (TARGET_ARC700)			\
+-      {					\
+-	builtin_define ("__A7__");	\
+-	builtin_define ("__ARC700__");	\
+-      }					\
+-    else if (TARGET_EM)			\
+-      {					\
+-	builtin_define ("__EM__");	\
+-      }					\
+-    else if (TARGET_HS)			\
+-      {					\
+-	builtin_define ("__HS__");	\
+-      }					\
+-    if (TARGET_ATOMIC)			\
+-      {					\
+-	builtin_define ("__ARC_ATOMIC__");	\
+-      }					\
+-    if (TARGET_NORM)			\
+-      {					\
+-	builtin_define ("__ARC_NORM__");\
+-	builtin_define ("__Xnorm");	\
+-      }					\
+-    if (TARGET_LL64)			\
+-      {					\
+-	builtin_define ("__ARC_LL64__");\
+-      }					\
+-    if (TARGET_MUL64_SET)		\
+-      builtin_define ("__ARC_MUL64__");\
+-    if (TARGET_MULMAC_32BY16_SET)	\
+-      builtin_define ("__ARC_MUL32BY16__");\
+-    if (TARGET_SIMD_SET)        	\
+-      builtin_define ("__ARC_SIMD__");	\
+-    if (TARGET_BARREL_SHIFTER)		\
+-      builtin_define ("__Xbarrel_shifter");\
+-    builtin_define_with_int_value ("__ARC_TLS_REGNO__", \
+-				   arc_tp_regno);	\
+-    builtin_assert ("cpu=arc");		\
+-    builtin_assert ("machine=arc");	\
+-    builtin_define (TARGET_BIG_ENDIAN	\
+-		    ? "__BIG_ENDIAN__" : "__LITTLE_ENDIAN__"); \
+-    if (TARGET_BIG_ENDIAN)		\
+-      builtin_define ("__big_endian__"); \
+-} while(0)
++#define TARGET_CPU_CPP_BUILTINS() arc_cpu_cpp_builtins (pfile)
+ 
+ #if DEFAULT_LIBC == LIBC_UCLIBC
+ 
+diff --git a/gcc/config/arc/t-arc b/gcc/config/arc/t-arc
+new file mode 100644
+index 000000000000..4252e73cabb5
+--- /dev/null
++++ b/gcc/config/arc/t-arc
+@@ -0,0 +1,29 @@
++# GCC Makefile fragment for Synopsys DesignWare ARC.
++#
++# Copyright (C) 2016 Free Software Foundation, Inc.
++#
++# This file is part of GCC.
++#
++# GCC is free software; you can redistribute it and/or modify it under the
++# terms of the GNU General Public License as published by the Free Software
++# Foundation; either version 3, or (at your option) any later version.
++#
++# GCC is distributed in the hope that it will be useful, but WITHOUT ANY
++# WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
++# FOR A PARTICULAR PURPOSE.  See the GNU General Public License for more
++# details.
++#
++# You should have received a copy of the GNU General Public License along
++# with GCC; see the file COPYING3.  If not see
++# <http://www.gnu.org/licenses/>.
++
++TM_H += $(srcdir)/config/arc/arc-c.def
++
++arc-c.o: $(srcdir)/config/arc/arc-c.c $(CONFIG_H) $(SYSTEM_H) \
++$(TREE_H) $(TM_H) $(TM_P_H) coretypes.h
++	$(COMPILER) -c $(ALL_COMPILERFLAGS) $(ALL_CPPFLAGS) $(INCLUDES) \
++		$(srcdir)/config/arc/arc-c.c
++
++# Local Variables:
++# mode: Makefile
++# End:
+-- 
+2.7.4
+
diff --git a/toolchain/gcc/patches/6.3.0/0021-Use-GOTOFFPC-relocation-for-pc-relative-accesses.patch b/toolchain/gcc/patches/6.3.0/0021-Use-GOTOFFPC-relocation-for-pc-relative-accesses.patch
new file mode 100644
index 0000000..7e0e7fe
--- /dev/null
+++ b/toolchain/gcc/patches/6.3.0/0021-Use-GOTOFFPC-relocation-for-pc-relative-accesses.patch
@@ -0,0 +1,197 @@
+From bef9f64e64899b7cda46a24e1ace689b88e06429 Mon Sep 17 00:00:00 2001
+From: Claudiu Zissulescu <claziss at synopsys.com>
+Date: Mon, 2 May 2016 15:45:14 +0200
+Subject: [PATCH 21/89] Use GOTOFFPC relocation for pc-relative accesses.
+
+gcc/
+2016-05-02  Claudiu Zissulescu  <claziss at synopsys.com>
+	    Joern Rennecke  <joern.rennecke at embecosm.com>
+
+	* config/arc/arc.c (arc_print_operand_address): Handle pc-relative
+	addresses.
+	(arc_needs_pcl_p): Add GOTOFFPC.
+	(arc_legitimate_pic_addr_p): Likewise.
+	(arc_output_pic_addr_const): Likewise.
+	(arc_legitimize_pic_address): Generate a pc-relative address using
+	GOTOFFPC.
+	(arc_output_libcall): Use @pcl syntax.
+	(arc_delegitimize_address_0): Delegitimize ARC_UNSPEC_GOTOFFPC.
+	* config/arc/arc.md ("unspec"): Add ARC_UNSPEC_GOTOFFPC.
+	(*movsi_insn): Use @pcl syntax.
+	(doloop_begin_i): Likewise.
+
+Signed-off-by: Claudiu Zissulescu <claziss at synopsys.com>
+---
+ gcc/config/arc/arc.c  | 53 ++++++++++++++++++++++++++++-----------------------
+ gcc/config/arc/arc.md |  6 ++++--
+ 2 files changed, 33 insertions(+), 26 deletions(-)
+
+diff --git a/gcc/config/arc/arc.c b/gcc/config/arc/arc.c
+index 49edc0a7f657..c0aa075cddb9 100644
+--- a/gcc/config/arc/arc.c
++++ b/gcc/config/arc/arc.c
+@@ -3528,7 +3528,8 @@ arc_print_operand_address (FILE *file , rtx addr)
+ 		 || XINT (c, 1) == UNSPEC_TLS_IE))
+ 	    || (GET_CODE (c) == PLUS
+ 		&& GET_CODE (XEXP (c, 0)) == UNSPEC
+-		&& (XINT (XEXP (c, 0), 1) == UNSPEC_TLS_OFF)))
++		&& (XINT (XEXP (c, 0), 1) == UNSPEC_TLS_OFF
++		    || XINT (XEXP (c, 0), 1) == ARC_UNSPEC_GOTOFFPC)))
+ 	  {
+ 	    arc_output_pic_addr_const (file, c, 0);
+ 	    break;
+@@ -4636,6 +4637,7 @@ arc_needs_pcl_p (rtx x)
+     switch (XINT (x, 1))
+       {
+       case ARC_UNSPEC_GOT:
++      case ARC_UNSPEC_GOTOFFPC:
+       case UNSPEC_TLS_GD:
+       case UNSPEC_TLS_IE:
+ 	return true;
+@@ -4698,9 +4700,10 @@ arc_legitimate_pic_addr_p (rtx addr)
+       || XVECLEN (addr, 0) != 1)
+     return false;
+ 
+-  /* Must be one of @GOT, @GOTOFF, @tlsgd, tlsie.  */
++  /* Must be one of @GOT, @GOTOFF, @GOTOFFPC, @tlsgd, tlsie.  */
+   if (XINT (addr, 1) != ARC_UNSPEC_GOT
+       && XINT (addr, 1) != ARC_UNSPEC_GOTOFF
++      && XINT (addr, 1) != ARC_UNSPEC_GOTOFFPC
+       && XINT (addr, 1) != UNSPEC_TLS_GD
+       && XINT (addr, 1) != UNSPEC_TLS_IE)
+     return false;
+@@ -4917,26 +4920,15 @@ arc_legitimize_pic_address (rtx orig, rtx oldx)
+       else if (!flag_pic)
+ 	return orig;
+       else if (CONSTANT_POOL_ADDRESS_P (addr) || SYMBOL_REF_LOCAL_P (addr))
+-	{
+-	  /* This symbol may be referenced via a displacement from the
+-	     PIC base address (@GOTOFF).  */
++	return gen_rtx_CONST (Pmode,
++			      gen_rtx_UNSPEC (Pmode, gen_rtvec (1, addr),
++			      ARC_UNSPEC_GOTOFFPC));
+ 
+-	  /* FIXME: if we had a way to emit pc-relative adds that
+-	     don't create a GOT entry, we could do without the use of
+-	     the gp register.  */
+-	  crtl->uses_pic_offset_table = 1;
+-	  pat = gen_rtx_UNSPEC (Pmode, gen_rtvec (1, addr), ARC_UNSPEC_GOTOFF);
+-	  pat = gen_rtx_CONST (Pmode, pat);
+-	  pat = gen_rtx_PLUS (Pmode, pic_offset_table_rtx, pat);
+-	}
+-      else
+-	{
+-	  /* This symbol must be referenced via a load from the
+-	     Global Offset Table (@GOTPC).  */
+-	  pat = gen_rtx_UNSPEC (Pmode, gen_rtvec (1, addr), ARC_UNSPEC_GOT);
+-	  pat = gen_rtx_CONST (Pmode, pat);
+-	  pat = gen_const_mem (Pmode, pat);
+-	}
++      /* This symbol must be referenced via a load from the Global
++	 Offset Table (@GOTPC).  */
++      pat = gen_rtx_UNSPEC (Pmode, gen_rtvec (1, addr), ARC_UNSPEC_GOT);
++      pat = gen_rtx_CONST (Pmode, pat);
++      pat = gen_const_mem (Pmode, pat);
+ 
+       if (oldx == NULL)
+ 	oldx = gen_reg_rtx (Pmode);
+@@ -4952,6 +4944,7 @@ arc_legitimize_pic_address (rtx orig, rtx oldx)
+ 	  if (GET_CODE (addr) == UNSPEC)
+ 	    {
+ 	      /* Check that the unspec is one of the ones we generate?  */
++	      return orig;
+ 	    }
+ 	  else
+ 	    gcc_assert (GET_CODE (addr) == PLUS);
+@@ -5105,6 +5098,9 @@ arc_output_pic_addr_const (FILE * file, rtx x, int code)
+ 	case ARC_UNSPEC_GOTOFF:
+ 	  suffix = "@gotoff";
+ 	  break;
++	case ARC_UNSPEC_GOTOFFPC:
++	  suffix = "@pcl",   pcrel = true;
++	  break;
+ 	case ARC_UNSPEC_PLT:
+ 	  suffix = "@plt";
+ 	  break;
+@@ -5389,6 +5385,7 @@ arc_legitimate_constant_p (machine_mode mode, rtx x)
+ 	  {
+ 	  case ARC_UNSPEC_PLT:
+ 	  case ARC_UNSPEC_GOTOFF:
++	  case ARC_UNSPEC_GOTOFFPC:
+ 	  case ARC_UNSPEC_GOT:
+ 	  case UNSPEC_TLS_GD:
+ 	  case UNSPEC_TLS_IE:
+@@ -7648,7 +7645,7 @@ arc_output_libcall (const char *fname)
+      || (TARGET_MEDIUM_CALLS && arc_ccfsm_cond_exec_p ()))
+     {
+       if (flag_pic)
+-	sprintf (buf, "add r12,pcl,@%s-(.&-4)\n\tjl%%!%%* [r12]", fname);
++	sprintf (buf, "add r12,pcl,@%s at pcl\n\tjl%%!%%* [r12]", fname);
+       else
+ 	sprintf (buf, "jl%%! @%s", fname);
+     }
+@@ -8578,13 +8575,21 @@ arc_legitimize_address (rtx orig_x, rtx oldx, machine_mode mode)
+ static rtx
+ arc_delegitimize_address_0 (rtx x)
+ {
+-  rtx u, gp;
++  rtx u, gp, p;
+ 
+   if (GET_CODE (x) == CONST && GET_CODE (u = XEXP (x, 0)) == UNSPEC)
+     {
+-      if (XINT (u, 1) == ARC_UNSPEC_GOT)
++      if (XINT (u, 1) == ARC_UNSPEC_GOT
++	  || XINT (u, 1) == ARC_UNSPEC_GOTOFFPC)
+ 	return XVECEXP (u, 0, 0);
+     }
++  else if (GET_CODE (x) == CONST && GET_CODE (p = XEXP (x, 0)) == PLUS
++	   && GET_CODE (u = XEXP (p, 0)) == UNSPEC
++	   && (XINT (u, 1) == ARC_UNSPEC_GOT
++	       || XINT (u, 1) == ARC_UNSPEC_GOTOFFPC))
++    return gen_rtx_CONST
++	    (GET_MODE (x),
++	     gen_rtx_PLUS (GET_MODE (p), XVECEXP (u, 0, 0), XEXP (p, 1)));
+   else if (GET_CODE (x) == PLUS
+ 	   && ((REG_P (gp = XEXP (x, 0))
+ 		&& REGNO (gp) == PIC_OFFSET_TABLE_REGNUM)
+diff --git a/gcc/config/arc/arc.md b/gcc/config/arc/arc.md
+index a4ee08450a8c..1102c53da260 100644
+--- a/gcc/config/arc/arc.md
++++ b/gcc/config/arc/arc.md
+@@ -102,6 +102,7 @@
+ ;;  UNSPEC_GOT       4        symbol to be rerenced through the GOT
+ ;;  UNSPEC_GOTOFF    5        Local symbol.To be referenced relative to the
+ ;;                            GOTBASE.(Referenced as @GOTOFF)
++;;  UNSPEC_GOTOFFPC  6        Local symbol.  To be referenced pc-relative.
+ ;;  ----------------------------------------------------------------------------
+ 
+ (define_c_enum "unspec" [
+@@ -111,6 +112,7 @@
+   ARC_UNSPEC_PLT
+   ARC_UNSPEC_GOT
+   ARC_UNSPEC_GOTOFF
++  ARC_UNSPEC_GOTOFFPC
+   UNSPEC_TLS_GD
+   UNSPEC_TLS_LD
+   UNSPEC_TLS_IE
+@@ -725,7 +727,7 @@
+    * return INTVAL (operands[1]) & 0xffffff ? \"movbi.cl %0,%1 >> %p1,%p1,8;8\" : \"movbi.cl %0,%L1 >> 24,24,8;9\";
+    mov%? %0,%1		;10
+    add %0,%S1		;11
+-   * return arc_get_unalign () ? \"add %0,pcl,%1-.+2\" : \"add %0,pcl,%1-.\";
++   add %0,pcl,%1 at pcl    ;12
+    mov%? %0,%S1%&	;13
+    mov%? %0,%S1		;14
+    ld%? %0,%1%&		;15
+@@ -5155,7 +5157,7 @@
+ 	  /* ??? Can do better for when a scratch register
+ 	     is known.  But that would require extra testing.  */
+ 	  arc_clear_unalign ();
+-	  return ".p2align 2\;push_s r0\;add r0,pcl,24\;sr r0,[2]; LP_START\;add r0,pcl,.L__GCC__LP%1-.+2\;sr r0,[3]; LP_END\;pop_s r0";
++	  return ".p2align 2\;push_s r0\;add r0,pcl,24\;sr r0,[2]; LP_START\;add r0,pcl,.L__GCC__LP%1 at pcl\;sr r0,[3]; LP_END\;pop_s r0";
+ 	}
+       output_asm_insn ((size < 2048
+ 			? "lp .L__GCC__LP%1" : "sr .L__GCC__LP%1,[3]; LP_END"),
+-- 
+2.7.4
+
diff --git a/toolchain/gcc/patches/6.3.0/0022-ARC-New-option-handling-refurbish-multilib-support.patch b/toolchain/gcc/patches/6.3.0/0022-ARC-New-option-handling-refurbish-multilib-support.patch
new file mode 100644
index 0000000..4596175
--- /dev/null
+++ b/toolchain/gcc/patches/6.3.0/0022-ARC-New-option-handling-refurbish-multilib-support.patch
@@ -0,0 +1,2188 @@
+From b5d629696b5a0f5c138b70104cdcf58b21b66942 Mon Sep 17 00:00:00 2001
+From: Claudiu Zissulescu <claziss at synopsys.com>
+Date: Wed, 4 May 2016 15:36:09 +0200
+Subject: [PATCH 22/89] [ARC] New option handling, refurbish multilib support.
+
+gcc/
+2016-05-09  Claudiu Zissulescu  <claziss at synopsys.com>
+
+	* config/arc/arc-arch.h: New file.
+	* config/arc/arc-arches.def: Likewise.
+	* config/arc/arc-cpus.def: Likewise.
+	* config/arc/arc-options.def: Likewise.
+	* config/arc/t-multilib: Likewise.
+	* config/arc/genmultilib.awk: Likewise.
+	* config/arc/genoptions.awk: Likewise.
+	* config/arc/arc-tables.opt: Likewise.
+	* config/arc/driver-arc.c: Likewise.
+	* common/config/arc/arc-common.c (arc_handle_option): Trace
+	toggled options.
+	* config.gcc (arc*-*-*): Add arc-tables.opt to arc's extra
+	options; check for supported cpu against arc-cpus.def file.
+	(arc*-*-elf*, arc*-*-linux-uclibc*): Use new make fragment; define
+	TARGET_CPU_BUILD macro; add driver-arc.o as an extra object.
+	* config/arc/arc-c.def: Add emacs local variables.
+	* config/arc/arc-opts.h (processor_type): Use arc-cpus.def file.
+	(FPU_FPUS, FPU_FPUD, FPU_FPUDA, FPU_FPUDA_DIV, FPU_FPUDA_FMA)
+	(FPU_FPUDA_ALL, FPU_FPUS_DIV, FPU_FPUS_FMA, FPU_FPUS_ALL)
+	(FPU_FPUD_DIV, FPU_FPUD_FMA, FPU_FPUD_ALL): New defines.
+	(DEFAULT_arc_fpu_build): Define.
+	(DEFAULT_arc_mpy_option): Define.
+	* config/arc/arc-protos.h (arc_init): Delete.
+	* config/arc/arc.c (arc_cpu_name): New variable.
+	(arc_selected_cpu, arc_selected_arch, arc_arcem, arc_archs)
+	(arc_arc700, arc_arc600, arc_arc601): New variable.
+	(arc_init): Add static; remove selection of default tune value,
+	cleanup obsolete error messages.
+	(arc_override_options): Make use of .def files for selecting the
+	right cpu and option configurations.
+	* config/arc/arc.h (stdbool.h): Include.
+	(TARGET_CPU_DEFAULT): Define.
+	(CPP_SPEC): Remove mcpu=NPS400 handling.
+	(arc_cpu_to_as): Declare.
+	(EXTRA_SPEC_FUNCTIONS): Define.
+	(OPTION_DEFAULT_SPECS): Likewise.
+	(ASM_DEFAULT): Remove.
+	(ASM_SPEC): Use arc_cpu_to_as.
+	(DRIVER_SELF_SPECS): Remove deprecated options.
+	(arc_arc700, arc_arc600, arc_arc601, arc_arcem, arc_archs):
+	Declare.
+	(TARGET_ARC600, TARGET_ARC601, TARGET_ARC700, TARGET_EM)
+	(TARGET_HS, TARGET_V2, TARGET_ARC600): Make them use arc_arc*
+	variables.
+	(MULTILIB_DEFAULTS): Use ARC_MULTILIB_CPU_DEFAULT.
+	* config/arc/arc.md (attr_cpu): Remove.
+	* config/arc/arc.opt (arc_mpy_option): Make it target variable.
+	(mno-mpy): Deprecate.
+	(mcpu=ARC600, mcpu=ARC601, mcpu=ARC700, mcpu=NPS400, mcpu=ARCEM)
+	(mcpu=ARCHS): Remove.
+	(mcrc, mdsp-packa, mdvbf, mmac-d16, mmac-24, mtelephony, mrtsc):
+	Deprecate.
+	(mbarrel_shifte, mspfp_, mdpfp_, mdsp_pack, mmac_): Remove.
+	(arc_fpu): Use new defines.
+	(arc_seen_options): New target variable.
+	* config/arc/t-arc (driver-arc.o): New target.
+	(arc-cpus, t-multilib, arc-tables.opt): Likewise.
+	* config/arc/t-arc-newlib: Delete.
+	* config/arc/t-arc-uClibc: Renamed to t-uClibc.
+	* doc/invoke.texi (ARC): Update arc options.
+---
+ gcc/common/config/arc/arc-common.c        | 162 ++++++++++++++++--------
+ gcc/config.gcc                            |  47 +++----
+ gcc/config/arc/arc-arch.h                 | 120 ++++++++++++++++++
+ gcc/config/arc/arc-arches.def             |  35 +++++
+ gcc/config/arc/arc-c.def                  |   4 +
+ gcc/config/arc/arc-cpus.def               |  47 +++++++
+ gcc/config/arc/arc-options.def            |  69 ++++++++++
+ gcc/config/arc/arc-opts.h                 |  47 ++++++-
+ gcc/config/arc/arc-protos.h               |   1 -
+ gcc/config/arc/arc-tables.opt             |  90 +++++++++++++
+ gcc/config/arc/arc.c                      | 186 +++++++++++++++------------
+ gcc/config/arc/arc.h                      |  91 ++++++-------
+ gcc/config/arc/arc.md                     |   5 -
+ gcc/config/arc/arc.opt                    | 109 +++++-----------
+ gcc/config/arc/driver-arc.c               |  80 ++++++++++++
+ gcc/config/arc/genmultilib.awk            | 204 ++++++++++++++++++++++++++++++
+ gcc/config/arc/genoptions.awk             |  85 +++++++++++++
+ gcc/config/arc/t-arc                      |  19 +++
+ gcc/config/arc/t-arc-newlib               |  46 -------
+ gcc/config/arc/t-multilib                 |  51 ++++++++
+ gcc/config/arc/{t-arc-uClibc => t-uClibc} |   0
+ gcc/doc/invoke.texi                       |  86 +++++++++++--
+ 22 files changed, 1228 insertions(+), 356 deletions(-)
+ create mode 100644 gcc/config/arc/arc-arch.h
+ create mode 100644 gcc/config/arc/arc-arches.def
+ create mode 100644 gcc/config/arc/arc-cpus.def
+ create mode 100644 gcc/config/arc/arc-options.def
+ create mode 100644 gcc/config/arc/arc-tables.opt
+ create mode 100644 gcc/config/arc/driver-arc.c
+ create mode 100644 gcc/config/arc/genmultilib.awk
+ create mode 100644 gcc/config/arc/genoptions.awk
+ delete mode 100644 gcc/config/arc/t-arc-newlib
+ create mode 100644 gcc/config/arc/t-multilib
+ rename gcc/config/arc/{t-arc-uClibc => t-uClibc} (100%)
+
+diff --git a/gcc/common/config/arc/arc-common.c b/gcc/common/config/arc/arc-common.c
+index f5b9c6d3cc98..0141e3d6a23c 100644
+--- a/gcc/common/config/arc/arc-common.c
++++ b/gcc/common/config/arc/arc-common.c
+@@ -2,6 +2,7 @@
+    Copyright (C) 1994-2016 Free Software Foundation, Inc.
+    Contributor: Joern Rennecke <joern.rennecke at embecosm.com>
+ 		on behalf of Synopsys Inc.
++		Claudiu Zissulescu <Claudiu.Zissulescu at synopsys.com>
+ 
+ This file is part of GCC.
+ 
+@@ -62,17 +63,19 @@ static const struct default_options arc_option_optimization_table[] =
+ 
+ /*  Process options.  */
+ static bool
+-arc_handle_option (struct gcc_options *opts, struct gcc_options *opts_set,
++arc_handle_option (struct gcc_options *opts,
++		   struct gcc_options *opts_set ATTRIBUTE_UNUSED,
+ 		   const struct cl_decoded_option *decoded,
+ 		   location_t loc)
+ {
+   size_t code = decoded->opt_index;
+   int value = decoded->value;
+   const char *arg = decoded->arg;
++  static int mcpu_seen = PROCESSOR_NONE;
++  char *p;
+ 
+   switch (code)
+     {
+-      static int mcpu_seen = PROCESSOR_NONE;
+     case OPT_mcpu_:
+       /* N.B., at this point arc_cpu has already been set to its new value by
+ 	 our caller, so comparing arc_cpu with PROCESSOR_NONE is pointless.  */
+@@ -80,71 +83,130 @@ arc_handle_option (struct gcc_options *opts, struct gcc_options *opts_set,
+       if (mcpu_seen != PROCESSOR_NONE && mcpu_seen != value)
+ 	warning_at (loc, 0, "multiple -mcpu= options specified.");
+       mcpu_seen = value;
++      break;
++
++    case OPT_mmpy_option_:
++      p = ASTRDUP (arg);
+ 
+-      switch (value)
++      if (!strcmp (p, "0")
++	  || !strcmp (p, "none"))
++	opts->x_arc_mpy_option = 0;
++      else if (!strcmp (p, "1")
++	  || !strcmp (p, "w"))
+ 	{
+-	case PROCESSOR_NPS400:
+-	  if (! (opts_set->x_TARGET_CASE_VECTOR_PC_RELATIVE) )
+-	    opts->x_TARGET_CASE_VECTOR_PC_RELATIVE = 1;
+-	  /* Fall through */
+-	case PROCESSOR_ARC600:
+-	case PROCESSOR_ARC700:
+-	  if (! (opts_set->x_target_flags & MASK_BARREL_SHIFTER) )
+-	    opts->x_target_flags |= MASK_BARREL_SHIFTER;
+-	  break;
+-	case PROCESSOR_ARC601:
+-	  if (! (opts_set->x_target_flags & MASK_BARREL_SHIFTER) )
+-	    opts->x_target_flags &= ~MASK_BARREL_SHIFTER;
+-	  break;
+-	case PROCESSOR_ARCHS:
+-	  if ( !(opts_set->x_target_flags & MASK_BARREL_SHIFTER))
+-	    opts->x_target_flags |= MASK_BARREL_SHIFTER;  /* Default: on.  */
+-	  if ( !(opts_set->x_target_flags & MASK_CODE_DENSITY))
+-	    opts->x_target_flags |= MASK_CODE_DENSITY;	  /* Default: on.  */
+-	  if ( !(opts_set->x_target_flags & MASK_NORM_SET))
+-	    opts->x_target_flags |= MASK_NORM_SET;	  /* Default: on.  */
+-	  if ( !(opts_set->x_target_flags & MASK_SWAP_SET))
+-	    opts->x_target_flags |= MASK_SWAP_SET;	  /* Default: on.  */
+-	  if ( !(opts_set->x_target_flags & MASK_DIVREM))
+-	    opts->x_target_flags |= MASK_DIVREM;	  /* Default: on.  */
+-	  break;
+-
+-	case PROCESSOR_ARCEM:
+-	  if ( !(opts_set->x_target_flags & MASK_BARREL_SHIFTER))
+-	    opts->x_target_flags |= MASK_BARREL_SHIFTER;  /* Default: on.  */
+-	  if ( !(opts_set->x_target_flags & MASK_CODE_DENSITY))
+-	    opts->x_target_flags &= ~MASK_CODE_DENSITY;	  /* Default: off.  */
+-	  if ( !(opts_set->x_target_flags & MASK_NORM_SET))
+-	    opts->x_target_flags &= ~MASK_NORM_SET;	  /* Default: off.  */
+-	  if ( !(opts_set->x_target_flags & MASK_SWAP_SET))
+-	    opts->x_target_flags &= ~MASK_SWAP_SET;	  /* Default: off.  */
+-	  if ( !(opts_set->x_target_flags & MASK_DIVREM))
+-	    opts->x_target_flags &= ~MASK_DIVREM;	  /* Default: off.  */
+-	  break;
+-	default:
+-	  gcc_unreachable ();
++	  opts->x_arc_mpy_option = 1;
++	  warning_at (loc, 0, "Unsupported value for mmpy-option");
+ 	}
++      else if (!strcmp (p, "2")
++	       || !strcmp (p, "mpy")
++	       || !strcmp (p, "wlh1"))
++	opts->x_arc_mpy_option = 2;
++      else if (!strcmp (p, "3")
++	       || !strcmp (p, "wlh2"))
++	opts->x_arc_mpy_option = 3;
++      else if (!strcmp (p, "4")
++	       || !strcmp (p, "wlh3"))
++	opts->x_arc_mpy_option = 4;
++      else if (!strcmp (p, "5")
++	       || !strcmp (p, "wlh4"))
++	opts->x_arc_mpy_option = 5;
++      else if (!strcmp (p, "6")
++	       || !strcmp (p, "wlh5"))
++	opts->x_arc_mpy_option = 6;
++      else if (!strcmp (p, "7")
++	       || !strcmp (p, "plus_dmpy"))
++	opts->x_arc_mpy_option = 7;
++      else if (!strcmp (p, "8")
++	       || !strcmp (p, "plus_macd"))
++	opts->x_arc_mpy_option = 8;
++      else if (!strcmp (p, "9")
++	       || !strcmp (p, "plus_qmacw"))
++	opts->x_arc_mpy_option = 9;
++      else
++	error_at (loc, "unknown value %qs for -mmpy-option", arg);
++
+       break;
+ 
+-    case OPT_mmpy_option_:
+-      if (value < 0 || value > 9)
+-	error_at (loc, "bad value %qs for -mmpy-option switch", arg);
++    case OPT_mcode_density:
++      opts->x_arc_seen_options |= MASK_CODE_DENSITY;
++      break;
++
++    case OPT_mdiv_rem:
++      opts->x_arc_seen_options |= MASK_DIVREM;
++      break;
++
++    case OPT_mnorm:
++      opts->x_arc_seen_options |= MASK_NORM_SET;
++      break;
++
++    case OPT_matomic:
++      opts->x_arc_seen_options |= MASK_ATOMIC;
++      break;
++
++    case OPT_mll64:
++      opts->x_arc_seen_options |= MASK_LL64;
++      break;
++
++    case OPT_mbarrel_shifter:
++      opts->x_arc_seen_options |= MASK_BARREL_SHIFTER;
++      break;
++
++    case OPT_mswap:
++      opts->x_arc_seen_options |= MASK_SWAP_SET;
++      break;
++
++    case OPT_mmul64:
++      opts->x_arc_seen_options |= MASK_MUL64_SET;
++      break;
++
++    case OPT_mmul32x16:
++      opts->x_arc_seen_options |= MASK_MULMAC_32BY16_SET;
++      break;
++
++    case OPT_mEA:
++      opts->x_arc_seen_options |= MASK_EA_SET;
++      break;
++
++    case OPT_mspfp:
++    case OPT_mspfp_compact:
++    case OPT_mspfp_fast:
++      opts->x_arc_seen_options |= MASK_SPFP_COMPACT_SET;
++      break;
++
++    case OPT_mdpfp:
++    case OPT_mdpfp_compact:
++    case OPT_mdpfp_fast:
++      opts->x_arc_seen_options |= MASK_DPFP_COMPACT_SET;
++      break;
++
++    case OPT_margonaut:
++      opts->x_arc_seen_options |= MASK_ARGONAUT_SET;
++      break;
++
++    case OPT_msimd:
++      opts->x_arc_seen_options |= MASK_SIMD_SET;
++      break;
++
++    default:
+       break;
+     }
+ 
+   return true;
+ }
+ 
++#undef  TARGET_OPTION_INIT_STRUCT
+ #define TARGET_OPTION_INIT_STRUCT arc_option_init_struct
++
++#undef  TARGET_OPTION_OPTIMIZATION_TABLE
+ #define TARGET_OPTION_OPTIMIZATION_TABLE arc_option_optimization_table
+-#define TARGET_HANDLE_OPTION arc_handle_option
+ 
+ #define DEFAULT_NO_SDATA (TARGET_SDATA_DEFAULT ? 0 : MASK_NO_SDATA_SET)
+ 
+-/* We default to ARC700, which has the barrel shifter enabled.  */
+-#define TARGET_DEFAULT_TARGET_FLAGS \
+-  (MASK_BARREL_SHIFTER|MASK_VOLATILE_CACHE_SET|DEFAULT_NO_SDATA)
++#undef  TARGET_DEFAULT_TARGET_FLAGS
++#define TARGET_DEFAULT_TARGET_FLAGS (DEFAULT_NO_SDATA | MASK_VOLATILE_CACHE_SET)
+ 
++#undef  TARGET_HANDLE_OPTION
++#define TARGET_HANDLE_OPTION arc_handle_option
+ 
+ #include "common/common-target-def.h"
+ 
+diff --git a/gcc/config.gcc b/gcc/config.gcc
+index 2cc649e1dc83..fbf77d3e6347 100644
+--- a/gcc/config.gcc
++++ b/gcc/config.gcc
+@@ -325,6 +325,7 @@ arc*-*-*)
+ 	cpu_type=arc
+ 	c_target_objs="arc-c.o"
+ 	cxx_target_objs="arc-c.o"
++	extra_options="${extra_options} arc/arc-tables.opt"
+ 	;;
+ arm*-*-*)
+ 	cpu_type=arm
+@@ -1002,13 +1003,12 @@ alpha*-dec-*vms*)
+ 	;;
+ arc*-*-elf*)
+ 	extra_headers="arc-simd.h"
+-	tm_file="dbxelf.h elfos.h newlib-stdint.h ${tm_file}"
+-	tmake_file="arc/t-arc-newlib arc/t-arc"
+-	case x"${with_cpu}" in
+-	  xarc600|xarc601|xarc700)
+-		target_cpu_default="TARGET_CPU_$with_cpu"
+-		;;
+-	esac
++	tm_file="arc/arc-arch.h dbxelf.h elfos.h newlib-stdint.h ${tm_file}"
++	tmake_file="arc/t-multilib arc/t-arc"
++	extra_gcc_objs="driver-arc.o"
++	if test "x$with_cpu" != x; then
++		tm_defines="${tm_defines} TARGET_CPU_BUILD=PROCESSOR_$with_cpu"
++	fi
+ 	if test x${with_endian} = x; then
+ 		case ${target} in
+ 		arc*be-*-* | arc*eb-*-*)	with_endian=big ;;
+@@ -1025,15 +1025,14 @@ arc*-*-elf*)
+ 	;;
+ arc*-*-linux-uclibc*)
+ 	extra_headers="arc-simd.h"
+-	tm_file="dbxelf.h elfos.h gnu-user.h linux.h glibc-stdint.h ${tm_file}"
+-	tmake_file="${tmake_file} arc/t-arc-uClibc arc/t-arc"
++	tm_file="arc/arc-arch.h dbxelf.h elfos.h gnu-user.h linux.h glibc-stdint.h ${tm_file}"
++	tmake_file="${tmake_file} arc/t-uClibc arc/t-arc"
+ 	tm_defines="${tm_defines} TARGET_SDATA_DEFAULT=0"
+ 	tm_defines="${tm_defines} TARGET_MMEDIUM_CALLS_DEFAULT=1"
+-	case x"${with_cpu}" in
+-	  xarc600|xarc601|xarc700)
+-		target_cpu_default="TARGET_CPU_$with_cpu"
+-		;;
+-	esac
++	extra_gcc_objs="driver-arc.o"
++	if test "x$with_cpu" != x; then
++		tm_defines="${tm_defines} TARGET_CPU_BUILD=PROCESSOR_$with_cpu"
++	fi
+ 	if test x${with_endian} = x; then
+ 		case ${target} in
+ 		arc*be-*-* | arc*eb-*-*)	with_endian=big ;;
+@@ -3693,15 +3692,19 @@ case "${target}" in
+ 		done
+ 		;;
+ 
+-	arc*-*-*) # was:	arc*-*-linux-uclibc)
++	arc*-*-*)
+ 		supported_defaults="cpu"
+-		case $with_cpu in
+-		  arc600|arc601|arc700)
+-			;;
+-		  *) echo "Unknown cpu type"
+-			exit 1
+-			;;
+-		esac
++
++		if [ x"$with_cpu" = x ] \
++		    || grep "^ARC_CPU ($with_cpu," \
++		       ${srcdir}/config/arc/arc-cpus.def \
++		       > /dev/null; then
++		 # Ok
++		 true
++		else
++		 echo "Unknown cpu used in --with-cpu=$with_cpu" 1>&2
++		 exit 1
++		fi
+ 		;;
+ 
+ 	arm*-*-*)
+diff --git a/gcc/config/arc/arc-arch.h b/gcc/config/arc/arc-arch.h
+new file mode 100644
+index 000000000000..c789296c9cc0
+--- /dev/null
++++ b/gcc/config/arc/arc-arch.h
+@@ -0,0 +1,120 @@
++/* Definitions of types that are used to store ARC architecture and
++   device information.
++   Copyright (C) 2016 Free Software Foundation, Inc.
++   Contributed by Claudiu Zissulescu (claziss at synopsys.com)
++
++This file is part of GCC.
++
++GCC is free software; you can redistribute it and/or modify
++it under the terms of the GNU General Public License as published by
++the Free Software Foundation; either version 3, or (at your option)
++any later version.
++
++GCC is distributed in the hope that it will be useful,
++but WITHOUT ANY WARRANTY; without even the implied warranty of
++MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
++GNU General Public License for more details.
++
++You should have received a copy of the GNU General Public License
++along with GCC; see the file COPYING3.  If not see
++<http://www.gnu.org/licenses/>.  */
++
++#ifndef GCC_ARC_ARCH_H
++#define GCC_ARC_ARCH_H
++
++#ifndef IN_LIBGCC2
++/* Architecture selection types.  */
++
++enum cpu_flags
++  {
++#define ARC_OPT(NAME, CODE, MASK, DOC)	 NAME = CODE,
++#define ARC_OPTX(NAME, CODE, VAR, VAL, DOC)	 NAME = CODE,
++#include "arc-options.def"
++#undef ARC_OPT
++#undef ARC_OPTX
++    FL_END
++  };
++
++
++/* ARC architecture variants.  */
++
++enum base_architecture
++  {
++    BASE_ARCH_NONE,
++#define ARC_ARCH(NAME, ARCH, FLAGS, DFLAGS)  BASE_ARCH_##ARCH,
++#include "arc-arches.def"
++#undef ARC_ARCH
++    BASE_ARCH_END
++  };
++
++
++/* Tune variants. Needs to match the attr_tune enum.  */
++
++enum arc_tune_attr
++  {
++    ARC_TUNE_NONE,
++    ARC_TUNE_ARC600,
++    ARC_TUNE_ARC700_4_2_STD,
++    ARC_TUNE_ARC700_4_2_XMAC
++  };
++
++/* CPU specific properties.  */
++
++typedef struct
++{
++  /* CPU name.  */
++  const char *const name;
++
++  /* Architecture class.  */
++  enum base_architecture arch;
++
++  /* Specific flags.  */
++  const unsigned long long flags;
++
++  /* Tune value.  */
++  enum arc_tune_attr tune;
++} arc_cpu_t;
++
++
++/* Architecture specific propoerties.  */
++
++typedef struct
++{
++  /* Architecture name.  */
++  const char *const name;
++
++  /* Architecture class.  */
++  enum base_architecture arch;
++
++  /* All allowed flags for this architecture.  */
++  const unsigned long long flags;
++
++  /* Default flags for this architecture.  It is a subset of
++     FLAGS.  */
++  const unsigned long long dflags;
++} arc_arch_t;
++
++
++
++const arc_arch_t arc_arch_types[] =
++  {
++    {"none", BASE_ARCH_NONE, 0, 0},
++#define ARC_ARCH(NAME, ARCH, FLAGS, DFLAGS)	\
++    {NAME, BASE_ARCH_##ARCH, FLAGS, DFLAGS},
++#include "arc-arches.def"
++#undef ARC_ARCH
++    {NULL, BASE_ARCH_END, 0, 0}
++  };
++
++const arc_cpu_t arc_cpu_types[] =
++  {
++    {"none", BASE_ARCH_NONE, 0, ARC_TUNE_NONE},
++#define ARC_CPU(NAME, ARCH, FLAGS, TUNE)	\
++    {#NAME, BASE_ARCH_##ARCH, FLAGS, ARC_TUNE_##TUNE},
++#include "arc-cpus.def"
++#undef ARC_CPU
++    {NULL, BASE_ARCH_END, 0, ARC_TUNE_NONE}
++  };
++
++#endif
++#endif /* GCC_ARC_ARCH_H */
+diff --git a/gcc/config/arc/arc-arches.def b/gcc/config/arc/arc-arches.def
+new file mode 100644
+index 000000000000..da69a1a8230c
+--- /dev/null
++++ b/gcc/config/arc/arc-arches.def
+@@ -0,0 +1,35 @@
++/* ARC ARCH architectures.
++   Copyright (C) 2016 Free Software Foundation, Inc.
++
++   This file is part of GCC.
++
++   GCC is free software; you can redistribute it and/or modify it
++   under the terms of the GNU General Public License as published
++   by the Free Software Foundation; either version 3, or (at your
++   option) any later version.
++
++   GCC is distributed in the hope that it will be useful, but WITHOUT
++   ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
++   or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public
++   License for more details.
++
++   You should have received a copy of the GNU General Public License
++   along with GCC; see the file COPYING3.  If not see
++   <http://www.gnu.org/licenses/>.  */
++
++ARC_ARCH("arcem", em, FL_MPYOPT_1_6 | FL_DIVREM | FL_CD | FL_NORM	\
++	 | FL_BS | FL_SWAP | FL_FPUS | FL_SPFP | FL_DPFP		\
++	 | FL_SIMD | FL_FPUDA, 0)
++ARC_ARCH("archs", hs, FL_MPYOPT_7_9 | FL_DIVREM | FL_NORM | FL_CD	\
++	 | FL_ATOMIC | FL_LL64 | FL_BS | FL_SWAP			\
++	 | FL_FPUS | FL_FPUD,						\
++	 FL_CD | FL_ATOMIC | FL_BS | FL_NORM | FL_SWAP)
++ARC_ARCH("arc6xx", 6xx, FL_BS | FL_NORM | FL_SWAP | FL_MUL64 | FL_MUL32x16 \
++	 | FL_SPFP | FL_ARGONAUT | FL_DPFP, 0)
++ARC_ARCH("arc700", 700, FL_ATOMIC | FL_BS | FL_NORM | FL_SWAP | FL_EA \
++	 | FL_SIMD | FL_SPFP | FL_ARGONAUT | FL_DPFP,		      \
++	 FL_BS | FL_NORM | FL_SWAP)
++
++/* Local Variables: */
++/* mode: c */
++/* End: */
+diff --git a/gcc/config/arc/arc-c.def b/gcc/config/arc/arc-c.def
+index 065e97360ded..4cfd7b6e35fd 100644
+--- a/gcc/config/arc/arc-c.def
++++ b/gcc/config/arc/arc-c.def
+@@ -66,3 +66,7 @@ ARC_C_DEF ("__EM__",     TARGET_EM)
+ ARC_C_DEF ("__HS__",     TARGET_HS)
+ ARC_C_DEF ("__Xnorm",    TARGET_NORM)
+ ARC_C_DEF ("__Xbarrel_shifter", TARGET_BARREL_SHIFTER)
++
++/* Local Variables: */
++/* mode: c */
++/* End: */
+diff --git a/gcc/config/arc/arc-cpus.def b/gcc/config/arc/arc-cpus.def
+new file mode 100644
+index 000000000000..6d93c89e04a4
+--- /dev/null
++++ b/gcc/config/arc/arc-cpus.def
+@@ -0,0 +1,47 @@
++/* ARC CPU architectures.
++   Copyright (C) 2016 Free Software Foundation, Inc.
++
++   This file is part of GCC.
++
++   GCC is free software; you can redistribute it and/or modify it
++   under the terms of the GNU General Public License as published
++   by the Free Software Foundation; either version 3, or (at your
++   option) any later version.
++
++   GCC is distributed in the hope that it will be useful, but WITHOUT
++   ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
++   or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public
++   License for more details.
++
++   You should have received a copy of the GNU General Public License
++   along with GCC; see the file COPYING3.  If not see
++   <http://www.gnu.org/licenses/>.  */
++
++ARC_CPU (em,        em, 0, NONE)
++ARC_CPU (arcem,     em, FL_MPYOPT_2|FL_CD|FL_BS, NONE)
++ARC_CPU (em4,       em, FL_CD, NONE)
++ARC_CPU (em4_dmips, em, FL_MPYOPT_2|FL_CD|FL_DIVREM|FL_NORM|FL_SWAP|FL_BS, NONE)
++ARC_CPU (em4_fpus,  em, FL_MPYOPT_2|FL_CD|FL_DIVREM|FL_NORM|FL_SWAP|FL_BS|FL_FPU_FPUS, NONE)
++ARC_CPU (em4_fpuda, em, FL_MPYOPT_2|FL_CD|FL_DIVREM|FL_NORM|FL_SWAP|FL_BS|FL_FPU_FPUDA, NONE)
++
++ARC_CPU (hs,         hs, 0, NONE)
++ARC_CPU (archs,      hs, FL_MPYOPT_2|FL_DIVREM|FL_LL64, NONE)
++ARC_CPU (hs34,       hs, FL_MPYOPT_2, NONE)
++ARC_CPU (hs38,       hs, FL_MPYOPT_9|FL_DIVREM|FL_LL64, NONE)
++ARC_CPU (hs38_linux, hs, FL_MPYOPT_9|FL_DIVREM|FL_LL64|FL_FPU_FPUD_ALL, NONE)
++
++ARC_CPU (arc600,          6xx, FL_BS, ARC600)
++ARC_CPU (arc600_norm,     6xx, FL_BS|FL_NORM, ARC600)
++ARC_CPU (arc600_mul64,    6xx, FL_BS|FL_NORM|FL_MUL64, ARC600)
++ARC_CPU (arc600_mul32x16, 6xx, FL_BS|FL_NORM|FL_MUL32x16, ARC600)
++ARC_CPU (arc601,          6xx, 0, ARC600)
++ARC_CPU (arc601_norm,     6xx, FL_NORM, ARC600)
++ARC_CPU (arc601_mul64,    6xx, FL_NORM|FL_MUL64, ARC600)
++ARC_CPU (arc601_mul32x16, 6xx, FL_NORM|FL_MUL32x16, ARC600)
++
++ARC_CPU (arc700, 700, 0, ARC700_4_2_STD)
++ARC_CPU (nps400, 700, 0, ARC700_4_2_STD)
++
++/* Local Variables: */
++/* mode: c */
++/* End: */
+diff --git a/gcc/config/arc/arc-options.def b/gcc/config/arc/arc-options.def
+new file mode 100644
+index 000000000000..3834894a0884
+--- /dev/null
++++ b/gcc/config/arc/arc-options.def
+@@ -0,0 +1,69 @@
++/* ARC options.
++   Copyright (C) 2016 Free Software Foundation, Inc.
++
++   This file is part of GCC.
++
++   GCC is free software; you can redistribute it and/or modify it
++   under the terms of the GNU General Public License as published
++   by the Free Software Foundation; either version 3, or (at your
++   option) any later version.
++
++   GCC is distributed in the hope that it will be useful, but WITHOUT
++   ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
++   or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public
++   License for more details.
++
++   You should have received a copy of the GNU General Public License
++   along with GCC; see the file COPYING3.  If not see
++   <http://www.gnu.org/licenses/>.  */
++
++ARC_OPT (FL_CD,       (1ULL << 0), MASK_CODE_DENSITY,      "code density")
++ARC_OPT (FL_DIVREM,   (1ULL << 1), MASK_DIVREM,            "div/rem")
++ARC_OPT (FL_NORM,     (1ULL << 2), MASK_NORM_SET,          "norm")
++
++ARC_OPT (FL_ATOMIC,   (1ULL << 4), MASK_ATOMIC,            "atomic")
++ARC_OPT (FL_LL64,     (1ULL << 5), MASK_LL64,              "double load/store")
++ARC_OPT (FL_BS,       (1ULL << 6), MASK_BARREL_SHIFTER,    "barrel shifter")
++ARC_OPT (FL_SWAP,     (1ULL << 7), MASK_SWAP_SET,          "swap")
++ARC_OPT (FL_MUL64,    (1ULL << 8), MASK_MUL64_SET,         "mul64")
++ARC_OPT (FL_MUL32x16, (1ULL << 9), MASK_MULMAC_32BY16_SET, "mul32x16")
++
++ARC_OPT (FL_EA,       (1ULL << 11), MASK_EA_SET,           "extended arithmetics")
++ARC_OPT (FL_SPFP,     (1ULL << 12), MASK_SPFP_COMPACT_SET, "single precission FPX")
++ARC_OPT (FL_DPFP,     (1ULL << 13), MASK_DPFP_COMPACT_SET, "double precission FPX")
++ARC_OPT (FL_ARGONAUT, (1ULL << 14), MASK_ARGONAUT_SET,     "argonaut")
++ARC_OPT (FL_SIMD,     (1ULL << 15), MASK_SIMD_SET,         "simd")
++
++ARC_OPTX (FL_MPYOPT_1, (1ULL << 17), arc_mpy_option, 1, "mpy option w")
++ARC_OPTX (FL_MPYOPT_2, (1ULL << 18), arc_mpy_option, 2, "mpy option wlh1")
++ARC_OPTX (FL_MPYOPT_3, (1ULL << 19), arc_mpy_option, 3, "mpy option wlh2")
++ARC_OPTX (FL_MPYOPT_4, (1ULL << 20), arc_mpy_option, 4, "mpy option wlh3")
++ARC_OPTX (FL_MPYOPT_5, (1ULL << 21), arc_mpy_option, 5, "mpy option wlh4")
++ARC_OPTX (FL_MPYOPT_6, (1ULL << 22), arc_mpy_option, 6, "mpy option wlh5")
++ARC_OPTX (FL_MPYOPT_7, (1ULL << 23), arc_mpy_option, 7, "mpy option plus_dmpy")
++ARC_OPTX (FL_MPYOPT_8, (1ULL << 24), arc_mpy_option, 8, "mpy option plus_macd")
++ARC_OPTX (FL_MPYOPT_9, (1ULL << 25), arc_mpy_option, 9, "mpy option plus_qmacw")
++
++ARC_OPT (FL_MPYOPT_7_9, (0x01c2ULL << 17), 0, "mpy option")
++ARC_OPT (FL_MPYOPT_1_6, (0x003fULL << 17), 0, "mpy option")
++
++ARC_OPTX (FL_FPU_FPUS,	    (1ULL << 26), arc_fpu_build, FPU_FPUS,	"mfpu=fpus")
++ARC_OPTX (FL_FPU_FPUS_DIV,  (1ULL << 27), arc_fpu_build, FPU_FPUS_DIV,	"mfpu=fpus_div")
++ARC_OPTX (FL_FPU_FPUS_FMA,  (1ULL << 28), arc_fpu_build, FPU_FPUS_FMA,	"mfpu=fpus_fma")
++ARC_OPTX (FL_FPU_FPUS_ALL,  (1ULL << 29), arc_fpu_build, FPU_FPUS_ALL,	"mfpu=fpus_all")
++ARC_OPTX (FL_FPU_FPUDA,	    (1ULL << 30), arc_fpu_build, FPU_FPUDA,	"mfpu=fpuda")
++ARC_OPTX (FL_FPU_FPUDA_DIV, (1ULL << 31), arc_fpu_build, FPU_FPUDA_DIV, "mfpu=fpuda_div")
++ARC_OPTX (FL_FPU_FPUDA_FMA, (1ULL << 32), arc_fpu_build, FPU_FPUDA_FMA, "mfpu=fpuda_fma")
++ARC_OPTX (FL_FPU_FPUDA_ALL, (1ULL << 33), arc_fpu_build, FPU_FPUDA_ALL, "mfpu=fpuda_all")
++ARC_OPTX (FL_FPU_FPUD,	    (1ULL << 34), arc_fpu_build, FPU_FPUD,	"mfpu=fpud")
++ARC_OPTX (FL_FPU_FPUD_DIV,  (1ULL << 35), arc_fpu_build, FPU_FPUD_DIV,	"mfpu=fpud_div")
++ARC_OPTX (FL_FPU_FPUD_FMA,  (1ULL << 36), arc_fpu_build, FPU_FPUD_FMA,	"mfpu=fpud_fma")
++ARC_OPTX (FL_FPU_FPUD_ALL,  (1ULL << 37), arc_fpu_build, FPU_FPUD_ALL,	"mfpu=fpud_all")
++
++ARC_OPT (FL_FPUS,  (0xFULL << 26), 0, "single precission floating point")
++ARC_OPT (FL_FPUDA, (0xFFULL << 26), 0, "double precission fp assist")
++ARC_OPT (FL_FPUD,  (0xF0FULL << 26), 0, "double precission floating point")
++
++/* Local Variables: */
++/* mode: c */
++/* End: */
+diff --git a/gcc/config/arc/arc-opts.h b/gcc/config/arc/arc-opts.h
+index cbd78985dd8b..81446b4a412a 100644
+--- a/gcc/config/arc/arc-opts.h
++++ b/gcc/config/arc/arc-opts.h
+@@ -18,15 +18,16 @@
+    along with GCC; see the file COPYING3.  If not see
+    <http://www.gnu.org/licenses/>.  */
+ 
++#ifndef ARC_OPTS_H
++#define ARC_OPTS_H
++
+ enum processor_type
+ {
+-  PROCESSOR_NONE,
+-  PROCESSOR_ARC600,
+-  PROCESSOR_ARC601,
+-  PROCESSOR_ARC700,
+-  PROCESSOR_NPS400,
+-  PROCESSOR_ARCEM,
+-  PROCESSOR_ARCHS
++  PROCESSOR_NONE = 0,
++#define ARC_CPU(NAME, ARCH, FLAGS, TUNE)  PROCESSOR_##NAME,
++#include "arc-cpus.def"
++#undef ARC_CPU
++  PROCESSOR_generic
+ };
+ 
+ /* Single precision floating point.  */
+@@ -48,3 +49,35 @@ enum processor_type
+ /* Double precision floating point assist operations.  */
+ #define FPX_DP    0x0100
+ 
++/* fpus option combi.  */
++#define FPU_FPUS  (FPU_SP | FPU_SC)
++/* fpud option combi.  */
++#define FPU_FPUD  (FPU_SP | FPU_SC | FPU_DP | FPU_DC)
++/* fpuda option combi.  */
++#define FPU_FPUDA (FPU_SP | FPU_SC | FPX_DP)
++/* fpuda_div option combi.  */
++#define FPU_FPUDA_DIV (FPU_SP | FPU_SC | FPU_SD | FPX_DP)
++/* fpuda_fma option combi.  */
++#define FPU_FPUDA_FMA (FPU_SP | FPU_SC | FPU_SF | FPX_DP)
++/* fpuda_all option combi.  */
++#define FPU_FPUDA_ALL (FPU_SP | FPU_SC | FPU_SF | FPU_SD | FPX_DP)
++/* fpus_div option combi.  */
++#define FPU_FPUS_DIV  (FPU_SP | FPU_SC | FPU_SD)
++/* fpus_fma option combi.  */
++#define FPU_FPUS_FMA  (FPU_SP | FPU_SC | FPU_SF)
++/* fpus_all option combi.  */
++#define FPU_FPUS_ALL  (FPU_SP | FPU_SC | FPU_SF | FPU_SD)
++/* fpud_div option combi.  */
++#define FPU_FPUD_DIV  (FPU_FPUS_DIV | FPU_DP | FPU_DC | FPU_DD)
++/* fpud_fma option combi.  */
++#define FPU_FPUD_FMA  (FPU_FPUS_FMA | FPU_DP | FPU_DC | FPU_DF)
++/* fpud_all option combi.  */
++#define FPU_FPUD_ALL  (FPU_FPUS_ALL | FPU_DP | FPU_DC | FPU_DF | FPU_DD)
++
++/* Default FPU option value.  */
++#define DEFAULT_arc_fpu_build 0x10000000
++
++/* Default MPY option value.  */
++#define DEFAULT_arc_mpy_option -1
++
++#endif /* ARC_OPTS_H */
+diff --git a/gcc/config/arc/arc-protos.h b/gcc/config/arc/arc-protos.h
+index b6ed39268c25..0e9476699ee3 100644
+--- a/gcc/config/arc/arc-protos.h
++++ b/gcc/config/arc/arc-protos.h
+@@ -52,7 +52,6 @@ extern enum arc_function_type arc_compute_function_type (struct function *);
+ #endif /* TREE_CODE */
+ 
+ 
+-extern void arc_init (void);
+ extern unsigned int arc_compute_frame_size (int);
+ extern bool arc_ccfsm_branch_deleted_p (void);
+ extern void arc_ccfsm_record_branch_deleted (void);
+diff --git a/gcc/config/arc/arc-tables.opt b/gcc/config/arc/arc-tables.opt
+new file mode 100644
+index 000000000000..0e7c50c7be78
+--- /dev/null
++++ b/gcc/config/arc/arc-tables.opt
+@@ -0,0 +1,90 @@
++; Auto-generated Makefile Snip
++; Generated by    : ./gcc/config/arc/genoptions.awk
++; Generated from  : ./gcc/config/arc/arc-cpu.def
++;
++; Copyright (C) 2016 Free Software Foundation, Inc.
++;
++; This file is part of GCC.
++;
++; GCC is free software; you can redistribute it and/or modify it under
++; the terms of the GNU General Public License as published by the Free
++; Software Foundation; either version 3, or (at your option) any later
++; version.
++;
++; GCC is distributed in the hope that it will be useful, but WITHOUT ANY
++; WARRANTY; without even the implied warranty of MERCHANTABILITY or
++; FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
++; for more details.
++;
++; You should have received a copy of the GNU General Public License
++; along with GCC; see the file COPYING3.  If not see
++; <http://www.gnu.org/licenses/>.
++
++Enum
++Name(processor_type) Type(enum processor_type)
++Known ARC CPUs (for use with the -mcpu= option):
++
++EnumValue
++Enum(processor_type) String(em) Value(PROCESSOR_em)
++
++EnumValue
++Enum(processor_type) String(arcem) Value(PROCESSOR_arcem)
++
++EnumValue
++Enum(processor_type) String(em4) Value(PROCESSOR_em4)
++
++EnumValue
++Enum(processor_type) String(em4_dmips) Value(PROCESSOR_em4_dmips)
++
++EnumValue
++Enum(processor_type) String(em4_fpus) Value(PROCESSOR_em4_fpus)
++
++EnumValue
++Enum(processor_type) String(em4_fpuda) Value(PROCESSOR_em4_fpuda)
++
++EnumValue
++Enum(processor_type) String(hs) Value(PROCESSOR_hs)
++
++EnumValue
++Enum(processor_type) String(archs) Value(PROCESSOR_archs)
++
++EnumValue
++Enum(processor_type) String(hs34) Value(PROCESSOR_hs34)
++
++EnumValue
++Enum(processor_type) String(hs38) Value(PROCESSOR_hs38)
++
++EnumValue
++Enum(processor_type) String(hs38_linux) Value(PROCESSOR_hs38_linux)
++
++EnumValue
++Enum(processor_type) String(arc600) Value(PROCESSOR_arc600)
++
++EnumValue
++Enum(processor_type) String(arc600_norm) Value(PROCESSOR_arc600_norm)
++
++EnumValue
++Enum(processor_type) String(arc600_mul64) Value(PROCESSOR_arc600_mul64)
++
++EnumValue
++Enum(processor_type) String(arc600_mul32x16) Value(PROCESSOR_arc600_mul32x16)
++
++EnumValue
++Enum(processor_type) String(arc601) Value(PROCESSOR_arc601)
++
++EnumValue
++Enum(processor_type) String(arc601_norm) Value(PROCESSOR_arc601_norm)
++
++EnumValue
++Enum(processor_type) String(arc601_mul64) Value(PROCESSOR_arc601_mul64)
++
++EnumValue
++Enum(processor_type) String(arc601_mul32x16) Value(PROCESSOR_arc601_mul32x16)
++
++EnumValue
++Enum(processor_type) String(arc700) Value(PROCESSOR_arc700)
++
++EnumValue
++Enum(processor_type) String(nps400) Value(PROCESSOR_nps400)
++
++
+diff --git a/gcc/config/arc/arc.c b/gcc/config/arc/arc.c
+index c0aa075cddb9..985df8151d74 100644
+--- a/gcc/config/arc/arc.c
++++ b/gcc/config/arc/arc.c
+@@ -64,7 +64,8 @@ along with GCC; see the file COPYING3.  If not see
+ #include "alias.h"
+ 
+ /* Which cpu we're compiling for (ARC600, ARC601, ARC700).  */
+-static const char *arc_cpu_string = "";
++static char arc_cpu_name[10] = "";
++static const char *arc_cpu_string = arc_cpu_name;
+ 
+ /* ??? Loads can handle any constant, stores can only handle small ones.  */
+ /* OTOH, LIMMs cost extra, so their usefulness is limited.  */
+@@ -241,6 +242,16 @@ static bool arc_use_by_pieces_infrastructure_p (unsigned HOST_WIDE_INT,
+ 						enum by_pieces_operation op,
+ 						bool);
+ 
++static const arc_cpu_t *arc_selected_cpu;
++static const arc_arch_t *arc_selected_arch;
++
++/* Global var which sets the current compilation architecture.  */
++bool arc_arcem = false;
++bool arc_archs = false;
++bool arc_arc700 = false;
++bool arc_arc600 = false;
++bool arc_arc601 = false;
++
+ /* Implements target hook vector_mode_supported_p.  */
+ 
+ static bool
+@@ -668,47 +679,9 @@ make_pass_arc_predicate_delay_insns (gcc::context *ctxt)
+ 
+ /* Called by OVERRIDE_OPTIONS to initialize various things.  */
+ 
+-void
++static void
+ arc_init (void)
+ {
+-  enum attr_tune tune_dflt = TUNE_NONE;
+-
+-  switch (arc_cpu)
+-    {
+-    case PROCESSOR_ARC600:
+-      arc_cpu_string = "ARC600";
+-      tune_dflt = TUNE_ARC600;
+-      break;
+-
+-    case PROCESSOR_ARC601:
+-      arc_cpu_string = "ARC601";
+-      tune_dflt = TUNE_ARC600;
+-      break;
+-
+-    case PROCESSOR_ARC700:
+-      arc_cpu_string = "ARC700";
+-      tune_dflt = TUNE_ARC700_4_2_STD;
+-      break;
+-
+-    case PROCESSOR_NPS400:
+-      arc_cpu_string = "NPS400";
+-      tune_dflt = TUNE_ARC700_4_2_STD;
+-      break;
+-
+-    case PROCESSOR_ARCEM:
+-      arc_cpu_string = "EM";
+-      break;
+-
+-    case PROCESSOR_ARCHS:
+-      arc_cpu_string = "HS";
+-      break;
+-
+-    default:
+-      gcc_unreachable ();
+-    }
+-
+-  if (arc_tune == TUNE_NONE)
+-    arc_tune = tune_dflt;
+   /* Note: arc_multcost is only used in rtx_cost if speed is true.  */
+   if (arc_multcost < 0)
+     switch (arc_tune)
+@@ -739,18 +712,10 @@ arc_init (void)
+ 	break;
+       }
+ 
+-  /* Support mul64 generation only for ARC600.  */
+-  if (TARGET_MUL64_SET && (!TARGET_ARC600_FAMILY))
+-      error ("-mmul64 not supported for ARC700 or ARCv2");
+-
+   /* MPY instructions valid only for ARC700 or ARCv2.  */
+   if (TARGET_NOMPY_SET && TARGET_ARC600_FAMILY)
+       error ("-mno-mpy supported only for ARC700 or ARCv2");
+ 
+-  /* mul/mac instructions only for ARC600.  */
+-  if (TARGET_MULMAC_32BY16_SET && (!TARGET_ARC600_FAMILY))
+-      error ("-mmul32x16 supported only for ARC600 or ARC601");
+-
+   if (!TARGET_DPFP && TARGET_DPFP_DISABLE_LRSR)
+       error ("-mno-dpfp-lrsr supported only with -mdpfp");
+ 
+@@ -763,23 +728,11 @@ arc_init (void)
+   if (TARGET_SPFP_FAST_SET && TARGET_ARC600_FAMILY)
+     error ("-mspfp_fast not available on ARC600 or ARC601");
+ 
+-  /* FPX-3. No FPX extensions on pre-ARC600 cores.  */
+-  if ((TARGET_DPFP || TARGET_SPFP)
+-      && (!TARGET_ARCOMPACT_FAMILY && !TARGET_EM))
+-    error ("FPX extensions not available on pre-ARC600 cores");
+-
+-  /* FPX-4.  No FPX extensions mixed with FPU extensions for ARC HS
+-     cpus.  */
+-  if ((TARGET_DPFP || TARGET_SPFP)
+-      && TARGET_HARD_FLOAT
+-      && TARGET_HS)
++  /* FPX-4.  No FPX extensions mixed with FPU extensions.  */
++  if ((TARGET_DPFP_FAST_SET || TARGET_DPFP_COMPACT_SET || TARGET_SPFP)
++      && TARGET_HARD_FLOAT)
+     error ("No FPX/FPU mixing allowed");
+ 
+-  /* Only selected multiplier configurations are available for HS.  */
+-  if (TARGET_HS && ((arc_mpy_option > 2 && arc_mpy_option < 7)
+-		    || (arc_mpy_option == 1)))
+-    error ("This multiplier configuration is not available for HS cores");
+-
+   /* Warn for unimplemented PIC in pre-ARC700 cores, and disable flag_pic.  */
+   if (flag_pic && TARGET_ARC600_FAMILY)
+     {
+@@ -789,26 +742,6 @@ arc_init (void)
+       flag_pic = 0;
+     }
+ 
+-  if (TARGET_ATOMIC && !(TARGET_ARC700 || TARGET_HS))
+-    error ("-matomic is only supported for ARC700 or ARC HS cores");
+-
+-  /* ll64 ops only available for HS.  */
+-  if (TARGET_LL64 && !TARGET_HS)
+-    error ("-mll64 is only supported for ARC HS cores");
+-
+-  /* FPU support only for V2.  */
+-  if (TARGET_HARD_FLOAT)
+-    {
+-      if (TARGET_EM
+-	  && (arc_fpu_build & ~(FPU_SP | FPU_SF | FPU_SC | FPU_SD | FPX_DP)))
+-	error ("FPU double precision options are available for ARC HS only");
+-      if (TARGET_HS && (arc_fpu_build & FPX_DP))
+-	error ("FPU double precision assist "
+-	       "options are not available for ARC HS");
+-      if (!TARGET_HS && !TARGET_EM)
+-	error ("FPU options are available for ARCv2 architecture only");
+-    }
+-
+   arc_init_reg_tables ();
+ 
+   /* Initialize array for PRINT_OPERAND_PUNCT_VALID_P.  */
+@@ -853,7 +786,92 @@ static void
+ arc_override_options (void)
+ {
+   if (arc_cpu == PROCESSOR_NONE)
+-    arc_cpu = PROCESSOR_ARC700;
++    arc_cpu = TARGET_CPU_DEFAULT;
++
++  /* Set the default cpu options.  */
++  arc_selected_cpu = &arc_cpu_types[(int) arc_cpu];
++  arc_selected_arch = &arc_arch_types[(int) arc_selected_cpu->arch];
++
++  /* Set the architectures.  */
++  switch (arc_selected_arch->arch)
++    {
++    case BASE_ARCH_em:
++      arc_arcem = true;
++      arc_cpu_string = "EM";
++      break;
++    case BASE_ARCH_hs:
++      arc_archs = true;
++      arc_cpu_string = "HS";
++      break;
++    case BASE_ARCH_700:
++      arc_arc700 = true;
++      arc_cpu_string = "ARC700";
++      break;
++    case BASE_ARCH_6xx:
++      arc_cpu_string = "ARC600";
++      if (arc_selected_cpu->flags & FL_BS)
++	arc_arc600 = true;
++      else
++	arc_arc601 = true;
++      break;
++    default:
++      gcc_unreachable ();
++    }
++
++  /* Set cpu flags accordingly to architecture/selected cpu.  The cpu
++     specific flags are set in arc-common.c.  The architecture forces
++     the default hardware configurations in, regardless what command
++     line options are saying.  The CPU optional hw options can be
++     turned on or off.  */
++#define ARC_OPT(NAME, CODE, MASK, DOC)		\
++  do {						\
++    if ((arc_selected_cpu->flags & CODE)	\
++	&& ((arc_seen_options & MASK) == 0))	\
++      target_flags |= MASK;			\
++    if (arc_selected_arch->dflags & CODE)	\
++      target_flags |= MASK;			\
++  } while (0);
++#define ARC_OPTX(NAME, CODE, VAR, VAL, DOC)	\
++  do {						\
++    if ((arc_selected_cpu->flags & CODE)	\
++	&& (VAR == DEFAULT_##VAR))		\
++      VAR = VAL;				\
++    if (arc_selected_arch->dflags & CODE)	\
++      VAR = VAL;				\
++  } while (0);
++
++#include "arc-options.def"
++
++#undef ARC_OPTX
++#undef ARC_OPT
++
++  /* Check options against architecture options.  Throw an error if
++     option is not allowed.  */
++#define ARC_OPTX(NAME, CODE, VAR, VAL, DOC)			\
++  do {								\
++    if ((VAR == VAL)						\
++	&& (!(arc_selected_arch->flags & CODE)))		\
++      {								\
++	error ("%s is not available for %s architecture",	\
++	       DOC, arc_selected_arch->name);			\
++      }								\
++  } while (0);
++#define ARC_OPT(NAME, CODE, MASK, DOC)				\
++  do {								\
++    if ((target_flags & MASK)					\
++	&& (!(arc_selected_arch->flags & CODE)))		\
++      error ("%s is not available for %s architecture",		\
++	     DOC, arc_selected_arch->name);			\
++  } while (0);
++
++#include "arc-options.def"
++
++#undef ARC_OPTX
++#undef ARC_OPT
++
++  /* Set Tune option.  */
++  if (arc_tune == TUNE_NONE)
++    arc_tune = (enum attr_tune) arc_selected_cpu->tune;
+ 
+   if (arc_size_opt_level == 3)
+     optimize_size = 1;
+diff --git a/gcc/config/arc/arc.h b/gcc/config/arc/arc.h
+index c02e1cd4c777..f1705d587d2f 100644
+--- a/gcc/config/arc/arc.h
++++ b/gcc/config/arc/arc.h
+@@ -28,6 +28,8 @@ along with GCC; see the file COPYING3.  If not see
+ #ifndef GCC_ARC_H
+ #define GCC_ARC_H
+ 
++#include <stdbool.h>
++
+ /* Things to do:
+ 
+    - incscc, decscc?
+@@ -39,6 +41,10 @@ along with GCC; see the file COPYING3.  If not see
+ #define SYMBOL_FLAG_LONG_CALL	(SYMBOL_FLAG_MACH_DEP << 2)
+ #define SYMBOL_FLAG_CMEM	(SYMBOL_FLAG_MACH_DEP << 3)
+ 
++#ifndef TARGET_CPU_DEFAULT
++#define TARGET_CPU_DEFAULT	PROCESSOR_arc700
++#endif
++
+ /* Check if this symbol has a long_call attribute in its declaration */
+ #define SYMBOL_REF_LONG_CALL_P(X)	\
+ 	((SYMBOL_REF_FLAGS (X) & SYMBOL_FLAG_LONG_CALL) != 0)
+@@ -74,9 +80,11 @@ along with GCC; see the file COPYING3.  If not see
+       GNU_USER_TARGET_OS_CPP_BUILTINS (); \
+     } \
+   while (0)
+-#endif
+ 
+-/* Match the macros used in the assembler.  */
++#endif /* DEFAULT_LIBC == LIBC_UCLIBC */
++
++/* Macros enabled by specific command line option.  FIXME: to be
++   deprecatd.  */
+ #define CPP_SPEC "\
+ %{msimd:-D__Xsimd} %{mno-mpy:-D__Xno_mpy} %{mswap:-D__Xswap} \
+ %{mmin-max:-D__Xmin_max} %{mEA:-D__Xea} \
+@@ -85,34 +93,22 @@ along with GCC; see the file COPYING3.  If not see
+ %{mdsp-packa:-D__Xdsp_packa} %{mcrc:-D__Xcrc} %{mdvbf:-D__Xdvbf} \
+ %{mtelephony:-D__Xtelephony} %{mxy:-D__Xxy} %{mmul64: -D__Xmult32} \
+ %{mlock:-D__Xlock} %{mswape:-D__Xswape} %{mrtsc:-D__Xrtsc} \
+-%{mcpu=NPS400:-D__NPS400__} \
+-%{mcpu=nps400:-D__NPS400__} \
+-"
++%{mcpu=nps400:-D__NPS400__}"
+ 
+ #define CC1_SPEC "\
+ %{EB:%{EL:%emay not use both -EB and -EL}} \
+ %{EB:-mbig-endian} %{EL:-mlittle-endian} \
+ "
++extern const char *arc_cpu_to_as (int argc, const char **argv);
++
++#define EXTRA_SPEC_FUNCTIONS			\
++  { "cpu_to_as", arc_cpu_to_as },
++
++#define ASM_SPEC  "%{mbig-endian|EB:-EB} %{EL} "			\
++  "%:cpu_to_as(%{mcpu=*:%*}) %{mspfp*} %{mdpfp*} %{mfpu=fpuda*:-mfpuda}"
+ 
+-#define ASM_DEFAULT "-mARC700 -mEA"
+-
+-#define ASM_SPEC  "\
+-%{mbig-endian|EB:-EB} %{EL} \
+-%{mcpu=ARC600:-mARC600} \
+-%{mcpu=ARC601:-mARC601} \
+-%{mcpu=ARC700:-mARC700} \
+-%{mcpu=ARC700:-mEA} \
+-%{!mcpu=*:" ASM_DEFAULT "} \
+-%{mbarrel-shifter} %{mno-mpy} %{mmul64} %{mmul32x16:-mdsp-packa} %{mnorm} \
+-%{mswap} %{mEA} %{mmin-max} %{mspfp*} %{mdpfp*} %{mfpu=fpuda*:-mfpuda} \
+-%{msimd} \
+-%{mmac-d16} %{mmac-24} %{mdsp-packa} %{mcrc} %{mdvbf} %{mtelephony} %{mxy} \
+-%{mcpu=ARC700|!mcpu=*:%{mlock}} \
+-%{mcpu=ARC700|!mcpu=*:%{mswape}} \
+-%{mcpu=ARC700|!mcpu=*:%{mrtsc}} \
+-%{mcpu=ARCHS:-mHS} \
+-%{mcpu=ARCEM:-mEM} \
+-%{matomic:-mlock}"
++#define OPTION_DEFAULT_SPECS						\
++  {"cpu", "%{!mcpu=*:%{!mARC*:%{!marc*:%{!mA7:%{!mA6:-mcpu=%(VALUE)}}}}}" }
+ 
+ #if DEFAULT_LIBC == LIBC_UCLIBC
+ /* Note that the default is to link against dynamic libraries, if they are
+@@ -196,17 +192,11 @@ along with GCC; see the file COPYING3.  If not see
+ #define TARGET_MMEDIUM_CALLS_DEFAULT 0
+ #endif
+ 
+-#define DRIVER_SELF_SPECS DRIVER_ENDIAN_SELF_SPECS \
+-  "%{mARC600|mA6: -mcpu=ARC600 %<mARC600 %<mA6}" \
+-  "%{mARC601: -mcpu=ARC601 %<mARC601}" \
+-  "%{mARC700|mA7: -mcpu=ARC700 %<mARC700 %<mA7}" \
+-  "%{mbarrel_shifte*: -mbarrel-shifte%* %<mbarrel_shifte*}" \
+-  "%{mEA: -mea %<mEA}" \
+-  "%{mspfp_*: -mspfp-%* %<mspfp_*}" \
+-  "%{mdpfp_*: -mdpfp-%* %<mdpfp_*}" \
+-  "%{mdsp_pack*: -mdsp-pack%* %<mdsp_pack*}" \
+-  "%{mmac_*: -mmac-%* %<mmac_*}" \
+-  "%{multcost=*: -mmultcost=%* %<multcost=*}"
++#define DRIVER_SELF_SPECS DRIVER_ENDIAN_SELF_SPECS		   \
++  "%{mARC600|mA6: -mcpu=arc600 %<mARC600 %<mA6 %<mARC600}"	   \
++  "%{mARC601: -mcpu=arc601 %<mARC601}"				   \
++  "%{mARC700|mA7: -mcpu=arc700 %<mARC700 %<mA7}"		   \
++  "%{mEA: -mea %<mEA}"
+ 
+ /* Run-time compilation parameters selecting different hardware subsets.  */
+ 
+@@ -252,20 +242,23 @@ along with GCC; see the file COPYING3.  If not see
+    use conditional execution?  */
+ #define TARGET_AT_DBR_CONDEXEC  (!TARGET_ARC700 && !TARGET_V2)
+ 
+-#define TARGET_ARC600 (arc_cpu == PROCESSOR_ARC600)
+-#define TARGET_ARC601 (arc_cpu == PROCESSOR_ARC601)
+-#define TARGET_ARC700 (arc_cpu == PROCESSOR_ARC700	\
+-		       || arc_cpu == PROCESSOR_NPS400)
+-#define TARGET_EM     (arc_cpu == PROCESSOR_ARCEM)
+-#define TARGET_HS     (arc_cpu == PROCESSOR_ARCHS)
+-#define TARGET_V2							\
+-  ((arc_cpu == PROCESSOR_ARCHS) || (arc_cpu == PROCESSOR_ARCEM))
+-
+-/* Recast the cpu class to be the cpu attribute.  */
+-#define arc_cpu_attr ((enum attr_cpu)arc_cpu)
+-
+-#ifndef MULTILIB_DEFAULTS
+-#define MULTILIB_DEFAULTS { "mARC700" }
++extern bool arc_arcem;
++extern bool arc_archs;
++extern bool arc_arc700;
++extern bool arc_arc600;
++extern bool arc_arc601;
++
++#define TARGET_ARC600 (arc_arc600)
++#define TARGET_ARC601 (arc_arc601)
++#define TARGET_ARC700 (arc_arc700)
++#define TARGET_EM (arc_arcem)
++#define TARGET_HS (arc_archs)
++#define TARGET_V2 (TARGET_EM || TARGET_HS)
++
++#ifdef ARC_MULTILIB_CPU_DEFAULT
++# ifndef MULTILIB_DEFAULTS
++#  define MULTILIB_DEFAULTS { "mcpu=" ARC_MULTILIB_CPU_DEFAULT }
++# endif
+ #endif
+ 
+ #ifndef UNALIGNED_ACCESS_DEFAULT
+diff --git a/gcc/config/arc/arc.md b/gcc/config/arc/arc.md
+index 1102c53da260..5accf4a479b4 100644
+--- a/gcc/config/arc/arc.md
++++ b/gcc/config/arc/arc.md
+@@ -231,11 +231,6 @@
+ 	 (eq_attr "is_CALL" "yes") (const_string "yes")]
+ 	(const_string "no")))
+ 
+-
+-;; Attribute describing the processor
+-(define_attr "cpu" "none,ARC600,ARC700,ARCEM,ARCHS"
+-  (const (symbol_ref "arc_cpu_attr")))
+-
+ ;; true for compact instructions (those with _s suffix)
+ ;; "maybe" means compact unless we conditionalize the insn.
+ (define_attr "iscompact" "true,maybe,true_limm,maybe_limm,false"
+diff --git a/gcc/config/arc/arc.opt b/gcc/config/arc/arc.opt
+index d957a92dd6f0..19c5deb095f7 100644
+--- a/gcc/config/arc/arc.opt
++++ b/gcc/config/arc/arc.opt
+@@ -53,9 +53,12 @@ mARC700
+ Target Report
+ Same as -mA7.
+ 
++TargetVariable
++int arc_mpy_option = DEFAULT_arc_mpy_option
++
+ mmpy-option=
+-Target RejectNegative Joined UInteger Var(arc_mpy_option) Init(2)
+--mmpy-option={0,1,2,3,4,5,6,7,8,9} Compile ARCv2 code with a multiplier design option.  Option 2 is default on.
++Target RejectNegative Joined
++-mmpy-option=MPY Compile ARCv2 code with a multiplier design option.
+ 
+ mdiv-rem
+ Target Report Mask(DIVREM)
+@@ -100,7 +103,7 @@ Target Report Mask(MUL64_SET)
+ Generate mul64 and mulu64 instructions.
+ 
+ mno-mpy
+-Target Report Mask(NOMPY_SET)
++Target Report Mask(NOMPY_SET) Warn(%qs is deprecated)
+ Do not generate mpy instructions for ARC700.
+ 
+ mea
+@@ -167,45 +170,6 @@ mcpu=
+ Target RejectNegative Joined Var(arc_cpu) Enum(processor_type) Init(PROCESSOR_NONE)
+ -mcpu=CPU	Compile code for ARC variant CPU.
+ 
+-Enum
+-Name(processor_type) Type(enum processor_type)
+-
+-EnumValue
+-Enum(processor_type) String(ARC600) Value(PROCESSOR_ARC600)
+-
+-EnumValue
+-Enum(processor_type) String(arc600) Value(PROCESSOR_ARC600)
+-
+-EnumValue
+-Enum(processor_type) String(ARC601) Value(PROCESSOR_ARC601)
+-
+-EnumValue
+-Enum(processor_type) String(arc601) Value(PROCESSOR_ARC601)
+-
+-EnumValue
+-Enum(processor_type) String(ARC700) Value(PROCESSOR_ARC700)
+-
+-EnumValue
+-Enum(processor_type) String(arc700) Value(PROCESSOR_ARC700)
+-
+-EnumValue
+-Enum(processor_type) String(nps400) Value(PROCESSOR_NPS400)
+-
+-EnumValue
+-Enum(processor_type) String(NPS400) Value(PROCESSOR_NPS400)
+-
+-EnumValue
+-Enum(processor_type) String(ARCEM) Value(PROCESSOR_ARCEM)
+-
+-EnumValue
+-Enum(processor_type) String(arcem) Value(PROCESSOR_ARCEM)
+-
+-EnumValue
+-Enum(processor_type) String(ARCHS) Value(PROCESSOR_ARCHS)
+-
+-EnumValue
+-Enum(processor_type) String(archs) Value(PROCESSOR_ARCHS)
+-
+ msize-level=
+ Target RejectNegative Joined UInteger Var(arc_size_opt_level) Init(-1)
+ size optimization level: 0:none 1:opportunistic 2: regalloc 3:drop align, -Os.
+@@ -308,25 +272,25 @@ Expand adddi3 and subdi3 at rtl generation time into add.f / adc etc.
+ ; Flags used by the assembler, but for which we define preprocessor
+ ; macro symbols as well.
+ mcrc
+-Target Report
++Target Report Warn(%qs is deprecated)
+ Enable variable polynomial CRC extension.
+ 
+ mdsp-packa
+-Target Report
++Target Report Warn(%qs is deprecated)
+ Enable DSP 3.1 Pack A extensions.
+ 
+ mdvbf
+-Target Report
++Target Report Warn(%qs is deprecated)
+ Enable dual viterbi butterfly extension.
+ 
+ mmac-d16
+-Target Report Undocumented
++Target Report Undocumented Warn(%qs is deprecated)
+ 
+ mmac-24
+-Target Report Undocumented
++Target Report Undocumented Warn(%qs is deprecated)
+ 
+ mtelephony
+-Target Report RejectNegative
++Target Report RejectNegative Warn(%qs is deprecated)
+ Enable Dual and Single Operand Instructions for Telephony.
+ 
+ mxy
+@@ -343,7 +307,7 @@ Target Report
+ Enable swap byte ordering extension instruction.
+ 
+ mrtsc
+-Target Report
++Target Report Warn(%qs is deprecated)
+ Enable 64-bit Time-Stamp Counter extension instruction.
+ 
+ EB
+@@ -394,24 +358,6 @@ Target
+ multcost=
+ Target RejectNegative Joined
+ 
+-; Unfortunately, listing the full option name gives us clashes
+-; with OPT_opt_name being claimed for both opt_name and opt-name,
+-; so we leave out the last character or more.
+-mbarrel_shifte
+-Target Joined
+-
+-mspfp_
+-Target Joined
+-
+-mdpfp_
+-Target Joined
+-
+-mdsp_pack
+-Target Joined
+-
+-mmac_
+-Target Joined
+-
+ matomic
+ Target Report Mask(ATOMIC)
+ Enable atomic instructions.
+@@ -421,47 +367,47 @@ Target Report Mask(LL64)
+ Enable double load/store instructions for ARC HS.
+ 
+ mfpu=
+-Target RejectNegative Joined Enum(arc_fpu) Var(arc_fpu_build) Init(0)
++Target RejectNegative Joined Enum(arc_fpu) Var(arc_fpu_build) Init(DEFAULT_arc_fpu_build)
+ Specify the name of the target floating point configuration.
+ 
+ Enum
+ Name(arc_fpu) Type(int)
+ 
+ EnumValue
+-Enum(arc_fpu) String(fpus) Value(FPU_SP | FPU_SC)
++Enum(arc_fpu) String(fpus) Value(FPU_FPUS)
+ 
+ EnumValue
+-Enum(arc_fpu) String(fpud) Value(FPU_SP | FPU_SC | FPU_DP | FPU_DC)
++Enum(arc_fpu) String(fpud) Value(FPU_FPUD)
+ 
+ EnumValue
+-Enum(arc_fpu) String(fpuda) Value(FPU_SP | FPU_SC | FPX_DP)
++Enum(arc_fpu) String(fpuda) Value(FPU_FPUDA)
+ 
+ EnumValue
+-Enum(arc_fpu) String(fpuda_div) Value(FPU_SP | FPU_SC | FPU_SD | FPX_DP)
++Enum(arc_fpu) String(fpuda_div) Value(FPU_FPUDA_DIV)
+ 
+ EnumValue
+-Enum(arc_fpu) String(fpuda_fma) Value(FPU_SP | FPU_SC | FPU_SF | FPX_DP)
++Enum(arc_fpu) String(fpuda_fma) Value(FPU_FPUDA_FMA)
+ 
+ EnumValue
+-Enum(arc_fpu) String(fpuda_all) Value(FPU_SP | FPU_SC | FPU_SF | FPU_SD | FPX_DP)
++Enum(arc_fpu) String(fpuda_all) Value(FPU_FPUDA_ALL)
+ 
+ EnumValue
+-Enum(arc_fpu) String(fpus_div) Value(FPU_SP | FPU_SC | FPU_SD)
++Enum(arc_fpu) String(fpus_div) Value(FPU_FPUS_DIV)
+ 
+ EnumValue
+-Enum(arc_fpu) String(fpud_div) Value(FPU_SP | FPU_SC | FPU_SD | FPU_DP | FPU_DC | FPU_DD)
++Enum(arc_fpu) String(fpud_div) Value(FPU_FPUD_DIV)
+ 
+ EnumValue
+-Enum(arc_fpu) String(fpus_fma) Value(FPU_SP | FPU_SC | FPU_SF)
++Enum(arc_fpu) String(fpus_fma) Value(FPU_FPUS_FMA)
+ 
+ EnumValue
+-Enum(arc_fpu) String(fpud_fma) Value(FPU_SP | FPU_SC | FPU_SF | FPU_DP | FPU_DC | FPU_DF)
++Enum(arc_fpu) String(fpud_fma) Value(FPU_FPUD_FMA)
+ 
+ EnumValue
+-Enum(arc_fpu) String(fpus_all) Value(FPU_SP | FPU_SC | FPU_SF | FPU_SD)
++Enum(arc_fpu) String(fpus_all) Value(FPU_FPUS_ALL)
+ 
+ EnumValue
+-Enum(arc_fpu) String(fpud_all) Value(FPU_SP | FPU_SC | FPU_SF | FPU_SD | FPU_DP | FPU_DC | FPU_DF | FPU_DD)
++Enum(arc_fpu) String(fpud_all) Value(FPU_FPUD_ALL)
+ 
+ mtp-regno=
+ Target RejectNegative Joined UInteger Var(arc_tp_regno) Init(25)
+@@ -481,3 +427,6 @@ Enable use of NPS400 xld/xst extension.
+ munaligned-access
+ Target Report Var(unaligned_access) Init(UNALIGNED_ACCESS_DEFAULT)
+ Enable unaligned word and halfword accesses to packed data.
++
++TargetVariable
++unsigned int arc_seen_options = 0
+diff --git a/gcc/config/arc/driver-arc.c b/gcc/config/arc/driver-arc.c
+new file mode 100644
+index 000000000000..c51b70803413
+--- /dev/null
++++ b/gcc/config/arc/driver-arc.c
+@@ -0,0 +1,80 @@
++/* Subroutines for the gcc driver.
++   Copyright (C) 2016 Free Software Foundation, Inc.
++   Contributed by Claudiu Zissulescu <claziss at synopsys.com>
++
++   This file is part of GCC.
++
++   GCC is free software; you can redistribute it and/or modify it
++   under the terms of the GNU General Public License as published by
++   the Free Software Foundation; either version 3, or (at your option)
++   any later version.
++
++   GCC is distributed in the hope that it will be useful, but WITHOUT
++   ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
++   or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public
++   License for more details.
++
++   You should have received a copy of the GNU General Public License
++   along with GCC; see the file COPYING3.  If not see
++   <http://www.gnu.org/licenses/>.  */
++
++#include "config.h"
++#include "system.h"
++#include "coretypes.h"
++#include "tm.h"
++
++/* Returns command line parameters to pass to as.  */
++
++const char*
++arc_cpu_to_as (int argc, const char **argv)
++{
++  const char *name = NULL;
++  const arc_cpu_t *arc_selected_cpu;
++
++  /* No argument, check what is the default cpu.  */
++  if (argc == 0)
++    {
++      arc_selected_cpu = &arc_cpu_types[(int) TARGET_CPU_DEFAULT];
++    }
++  else
++    {
++      name = argv[0];
++      for (arc_selected_cpu = arc_cpu_types; arc_selected_cpu->name;
++	   arc_selected_cpu++)
++	{
++	  if (strcmp (arc_selected_cpu->name, name) == 0)
++	    break;
++	}
++    }
++
++  /* Checking the flags is only required with the old binutils
++     tools.  */
++  switch (arc_selected_cpu->arch)
++    {
++    case BASE_ARCH_em:
++      if (arc_selected_cpu->flags & FL_CD)
++	name = "-mcode-density";
++      else
++	name = "";
++      if (arc_selected_cpu->flags & FL_FPUDA)
++	name = concat ("-mfpuda ", name, NULL);
++      if (arc_selected_cpu->flags & FL_SPFP)
++	name = concat ("-mspfp ", name, NULL);
++      if (arc_selected_cpu->flags & FL_DPFP)
++	name = concat ("-mdpfp ", name, NULL);
++      return concat ("-mcpu=arcem ", name, NULL);
++    case BASE_ARCH_hs:
++      return "-mcpu=archs";
++    case BASE_ARCH_700:
++      return "-mcpu=arc700 -mEA";
++    case BASE_ARCH_6xx:
++      if (arc_selected_cpu->flags & FL_MUL64)
++	return "-mcpu=arc600 -mmul64 -mnorm";
++      if (arc_selected_cpu->flags & FL_MUL32x16)
++	return "-mcpu=arc600 -mdsp-packa -mnorm";
++      return "-mcpu=arc600 -mnorm";
++    default:
++      gcc_unreachable ();
++    }
++  return NULL;
++}
+diff --git a/gcc/config/arc/genmultilib.awk b/gcc/config/arc/genmultilib.awk
+new file mode 100644
+index 000000000000..61bda419c8a8
+--- /dev/null
++++ b/gcc/config/arc/genmultilib.awk
+@@ -0,0 +1,204 @@
++# Copyright (C) 2016 Free Software Foundation, Inc.
++#
++# This file is part of GCC.
++#
++# GCC is free software; you can redistribute it and/or modify it under
++# the terms of the GNU General Public License as published by the Free
++# Software Foundation; either version 3, or (at your option) any later
++# version.
++#
++# GCC is distributed in the hope that it will be useful, but WITHOUT ANY
++# WARRANTY; without even the implied warranty of MERCHANTABILITY or
++# FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
++# for more details.
++#
++# You should have received a copy of the GNU General Public License
++# along with GCC; see the file COPYING3.  If not see
++# <http://www.gnu.org/licenses/>.
++
++##################################################################
++#
++# This file is using AVR's genmultilib.awk idea.
++# Transform CPU Information from avr-cpu.def to a
++# Representation that is understood by GCC's multilib Machinery.
++#
++# The Script works as a Filter from STDIN to STDOUT.
++#
++# FORMAT = "Makefile": Generate Makefile Snipet that sets some
++#                      MULTILIB_* Variables as needed.
++#
++##################################################################
++
++BEGIN {
++  FS ="[(, \t)]+"
++  comment = 1
++  n_cores = 0
++  n_reuse = 0
++}
++
++##################################################################
++# Add some Comments to the generated Files and copy-paste
++# Copyright Notice from above.
++##################################################################
++/^#/ {
++  if (!comment)
++    next
++  else if (comment == 1)
++    {
++      if (FORMAT == "Makefile")
++	{
++	  print "# Auto-generated Makefile Snip"
++	  print "# Generated by    : ./gcc/config/arc/genmultilib.awk"
++	  print "# Generated from  : ./gcc/config/arc/arc-cpu.def"
++	  print "# Used by         : tmake_file from Makefile and genmultilib"
++	  print ""
++	}
++    }
++
++  comment = 2;
++
++  print
++}
++
++/^$/ {
++  # The first empty line stops copy-pasting the GPL comments
++  # from this file to the generated file.
++
++  comment = 0
++}
++
++
++/^ARC_CPU/ {
++  name = $2
++  #  gsub ("\"", "", name)
++
++  if ($4 != "0")
++    {
++      arch = $3
++      if (arch == "6xx")
++	arch = 601
++
++      n = split ($4, cpu_flg, "|")
++
++      line = "mcpu." arch
++      for (i = 1; i <= n; i++)
++	{
++	  if (cpu_flg[i] == "FL_MPYOPT_0")
++	    line = line "/mmpy-option.0"
++	  else if (cpu_flg[i] == "FL_MPYOPT_1")
++	    line = line "/mmpy-option.1"
++	  else if (cpu_flg[i] == "FL_MPYOPT_2")
++	    line = line "/mmpy-option.2"
++	  else if (cpu_flg[i] == "FL_MPYOPT_3")
++	    line = line "/mmpy-option.3"
++	  else if (cpu_flg[i] == "FL_MPYOPT_4")
++	    line = line "/mmpy-option.4"
++	  else if (cpu_flg[i] == "FL_MPYOPT_5")
++	    line = line "/mmpy-option.5"
++	  else if (cpu_flg[i] == "FL_MPYOPT_6")
++	    line = line "/mmpy-option.6"
++	  else if (cpu_flg[i] == "FL_MPYOPT_7")
++	    line = line "/mmpy-option.7"
++	  else if (cpu_flg[i] == "FL_MPYOPT_8")
++	    line = line "/mmpy-option.8"
++	  else if (cpu_flg[i] == "FL_MPYOPT_9")
++	    line = line "/mmpy-option.9"
++	  else if (cpu_flg[i] == "FL_CD")
++	    line = line "/mcode-density"
++	  else if (cpu_flg[i] == "FL_BS")
++	    line = line "/mbarrel-shifter"
++	  else if (cpu_flg[i] == "FL_DIVREM")
++	    line = line "/mdiv-rem"
++	  else if (cpu_flg[i] == "FL_NORM" \
++		   || cpu_flg[i] == "FL_SWAP") # SWAP option goes into norm folder.
++	    line = line "/mnorm"
++	  else if (cpu_flg[i] == "FL_FPU_FPUS")
++	    line = line "/mfpu.fpus"
++	  else if (cpu_flg[i] == "FL_FPU_FPUDA")
++	    line = line "/mfpu.fpuda"
++	  else if (cpu_flg[i] == "FL_FPU_FPUD_ALL")
++	    line = line "/mfpu.fpud_all"
++	  else if (cpu_flg[i] == "FL_LL64")
++	    line = line "/mll64"
++	  else if (cpu_flg[i] == "FL_MUL64")
++	    line = line "/mmul64"
++	  else if (cpu_flg[i] == "FL_MUL32x16")
++	    line = line "/mmul32x16"
++	  else if (cpu_flg[i] == "FL_FPX_QUARK")
++	    line = line "/quark"
++	  else if (cpu_flg[i] == "FL_SPFP")
++	    line = line "/spfp"
++	  else if (cpu_flg[i] == "FL_DPFP")
++	    line = line "/dpfp"
++	  else
++	    {
++	      print "Don't know the flag " cpu_flg[i] > "/dev/stderr"
++	      exit 1
++	    }
++	}
++      line = "mcpu." name "=" line
++      reuse[n_reuse] = line
++      n_reuse++
++    }
++
++  core = name
++  cores[n_cores] = core
++  n_cores++
++}
++
++##################################################################
++#
++# We gathered all the Information, now build/output the following:
++#
++#    awk Variable         target Variable          FORMAT
++#  -----------------------------------------------------------
++#    m_options     <->    MULTILIB_OPTIONS         Makefile
++#    m_dirnames    <->    MULTILIB_DIRNAMES           "
++#
++##################################################################
++
++END {
++  m_options    = "\nMULTILIB_OPTIONS = "
++  m_dirnames   = "\nMULTILIB_DIRNAMES ="
++  m_reuse      = "\nMULTILIB_REUSE ="
++
++  sep = ""
++  for (c = 0; c < n_cores; c++)
++    {
++      m_options  = m_options sep "mcpu=" cores[c]
++      m_dirnames = m_dirnames " " cores[c]
++      sep = "/"
++    }
++
++  sep = ""
++  for (c = 0; c < n_reuse; c++)
++    {
++      m_reuse = m_reuse sep reuse[c]
++      sep = "\nMULTILIB_REUSE +="
++    }
++  ############################################################
++  # Output that Stuff
++  ############################################################
++
++  if (FORMAT == "Makefile")
++    {
++      # Intended Target: ./gcc/config/arc/t-multilib
++
++      print m_options
++      print m_dirnames
++      print m_reuse
++
++      ############################################################
++      # Legacy Aliases
++      ############################################################
++
++      print ""
++      print "# Aliases:"
++      print "MULTILIB_MATCHES  = mcpu?arc600=mcpu?ARC600"
++      print "MULTILIB_MATCHES += mcpu?arc600=mARC600"
++      print "MULTILIB_MATCHES += mcpu?arc600=mA6"
++      print "MULTILIB_MATCHES += mcpu?arc601=mcpu?ARC601"
++      print "MULTILIB_MATCHES += mcpu?arc700=mA7"
++      print "MULTILIB_MATCHES += mcpu?arc700=mARC700"
++    }
++}
+diff --git a/gcc/config/arc/genoptions.awk b/gcc/config/arc/genoptions.awk
+new file mode 100644
+index 000000000000..816db6e83b92
+--- /dev/null
++++ b/gcc/config/arc/genoptions.awk
+@@ -0,0 +1,85 @@
++# Copyright (C) 2016 Free Software Foundation, Inc.
++#
++# This file is part of GCC.
++#
++# GCC is free software; you can redistribute it and/or modify it under
++# the terms of the GNU General Public License as published by the Free
++# Software Foundation; either version 3, or (at your option) any later
++# version.
++#
++# GCC is distributed in the hope that it will be useful, but WITHOUT ANY
++# WARRANTY; without even the implied warranty of MERCHANTABILITY or
++# FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
++# for more details.
++#
++# You should have received a copy of the GNU General Public License
++# along with GCC; see the file COPYING3.  If not see
++# <http://www.gnu.org/licenses/>.
++
++##################################################################
++#
++# This file is using AVR's genmultilib.awk idea.
++#
++##################################################################
++
++BEGIN {
++  FS ="[(, \t)]+"
++  comment = 1
++  n_cores = 0
++}
++
++##################################################################
++# Add some Comments to the generated Files and copy-paste
++# Copyright Notice from above.
++##################################################################
++/^#/ {
++  if (!comment)
++    next
++  else if (comment == 1)
++    {
++      if (FORMAT == "Makefile")
++	{
++	  print "; Auto-generated Makefile Snip"
++	  print "; Generated by    : ./gcc/config/arc/genoptions.awk"
++	  print "; Generated from  : ./gcc/config/arc/arc-cpu.def"
++	  print ";"
++	}
++    }
++
++  comment = 2;
++
++  gsub ("^#", ";", $0)
++  print
++}
++
++/^$/ {
++    # The first empty line stops copy-pasting the GPL comments
++    # from this file to the generated file.
++    comment = 0
++}
++
++/^ARC_CPU/ {
++  name = $2
++  cores[n_cores] = name;
++  n_cores++
++}
++
++END {
++  m_option = ""
++  for (c = 0; c < n_cores; c++)
++    {
++      m_options = m_options "EnumValue\nEnum(processor_type) String(" cores[c] ") Value(PROCESSOR_" cores[c] ")\n\n"
++    }
++
++  ############################################################
++  # Output that Stuff
++  ############################################################
++
++  if (FORMAT == "Makefile")
++    {
++	print "\nEnum"
++	print "Name(processor_type) Type(enum processor_type)"
++	print "Known ARC CPUs (for use with the -mcpu= option):\n"
++	print m_options
++    }
++}
+diff --git a/gcc/config/arc/t-arc b/gcc/config/arc/t-arc
+index 4252e73cabb5..f8e0b54f1dfc 100644
+--- a/gcc/config/arc/t-arc
++++ b/gcc/config/arc/t-arc
+@@ -19,11 +19,30 @@
+ 
+ TM_H += $(srcdir)/config/arc/arc-c.def
+ 
++driver-arc.o: $(srcdir)/config/arc/driver-arc.c \
++  $(CONFIG_H) $(SYSTEM_H) coretypes.h $(TM_H)
++	$(COMPILER) -c $(ALL_COMPILERFLAGS) $(ALL_CPPFLAGS) $(INCLUDES) $<
++
+ arc-c.o: $(srcdir)/config/arc/arc-c.c $(CONFIG_H) $(SYSTEM_H) \
+ $(TREE_H) $(TM_H) $(TM_P_H) coretypes.h
+ 	$(COMPILER) -c $(ALL_COMPILERFLAGS) $(ALL_CPPFLAGS) $(INCLUDES) \
+ 		$(srcdir)/config/arc/arc-c.c
+ 
++#Run `arc-cpus` if you changed something in arc-cpus.def
++
++.PHONY: arc-cpus
++
++arc-cpus: $(srcdir)/config/arc/t-multilib \
++	$(srcdir)/config/arc/arc-tables.opt
++
++$(srcdir)/config/arc/t-multilib: $(srcdir)/config/arc/genmultilib.awk \
++				 $(srcdir)/config/arc/arc-cpus.def
++	$(AWK) -f $< -v FORMAT=Makefile   $< $(srcdir)/config/arc/arc-cpus.def > $@
++
++$(srcdir)/config/arc/arc-tables.opt: $(srcdir)/config/arc/genoptions.awk \
++				 $(srcdir)/config/arc/arc-cpus.def
++	$(AWK) -f $< -v FORMAT=Makefile   $< $(srcdir)/config/arc/arc-cpus.def > $@
++
+ # Local Variables:
+ # mode: Makefile
+ # End:
+diff --git a/gcc/config/arc/t-arc-newlib b/gcc/config/arc/t-arc-newlib
+deleted file mode 100644
+index c49a3fcc146f..000000000000
+--- a/gcc/config/arc/t-arc-newlib
++++ /dev/null
+@@ -1,46 +0,0 @@
+-# GCC Makefile fragment for Synopsys DesignWare ARC with newlib.
+-
+-# Copyright (C) 2007-2016 Free Software Foundation, Inc.
+-
+-# This file is part of GCC.
+-
+-# GCC is free software; you can redistribute it and/or modify it under the
+-# terms of the GNU General Public License as published by the Free Software
+-# Foundation; either version 3, or (at your option) any later version.
+-
+-# GCC is distributed in the hope that it will be useful, but WITHOUT ANY
+-# WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
+-# FOR A PARTICULAR PURPOSE.  See the GNU General Public License for more
+-# details.
+-
+-# You should have received a copy of the GNU General Public License along
+-# with GCC; see the file COPYING3.  If not see
+-# <http://www.gnu.org/licenses/>.
+-
+-MULTILIB_OPTIONS=mcpu=ARC600/mcpu=ARC601/mcpu=ARC700/mcpu=ARCEM/mcpu=ARCHS mmul64/mmul32x16 mnorm
+-MULTILIB_DIRNAMES=arc600 arc601 arc700 em hs mul64 mul32x16 norm
+-#
+-# Aliases:
+-MULTILIB_MATCHES  = mcpu?ARC600=mcpu?arc600
+-MULTILIB_MATCHES += mcpu?ARC600=mARC600
+-MULTILIB_MATCHES += mcpu?ARC600=mA6
+-MULTILIB_MATCHES += mcpu?ARC600=mno-mpy
+-MULTILIB_MATCHES += mcpu?ARC601=mcpu?arc601
+-MULTILIB_MATCHES += mcpu?ARC700=mA7
+-MULTILIB_MATCHES += mcpu?ARC700=mARC700
+-MULTILIB_MATCHES += mcpu?ARC700=mcpu?arc700
+-MULTILIB_MATCHES += mcpu?ARCEM=mcpu?arcem
+-MULTILIB_MATCHES += mcpu?ARCHS=mcpu?archs
+-MULTILIB_MATCHES += EL=mlittle-endian
+-MULTILIB_MATCHES += EB=mbig-endian
+-#
+-# These don't make sense for the ARC700 default target:
+-MULTILIB_EXCEPTIONS=mmul64* mmul32x16* norm*
+-# And neither of the -mmul* options make sense without -mnorm:
+-MULTILIB_EXCLUSIONS=mARC600/mmul64/!mnorm mcpu=ARC601/mmul64/!mnorm mARC600/mmul32x16/!mnorm
+-# Exclusions for ARC700
+-MULTILIB_EXCEPTIONS += mcpu=ARC700/mnorm* mcpu=ARC700/mmul64* mcpu=ARC700/mmul32x16*
+-# Exclusions for ARCv2EM
+-MULTILIB_EXCEPTIONS += mcpu=ARCEM/mmul64* mcpu=ARCEM/mmul32x16*
+-# Exclusions for ARCv2HS
+-MULTILIB_EXCEPTIONS += mcpu=ARCHS/mmul64* mcpu=ARCHS/mmul32x16* mcpu=ARCHS/mnorm*
+diff --git a/gcc/config/arc/t-multilib b/gcc/config/arc/t-multilib
+new file mode 100644
+index 000000000000..1407bdf0d82c
+--- /dev/null
++++ b/gcc/config/arc/t-multilib
+@@ -0,0 +1,51 @@
++# Auto-generated Makefile Snip
++# Generated by    : ./gcc/config/arc/genmultilib.awk
++# Generated from  : ./gcc/config/arc/arc-cpu.def
++# Used by         : tmake_file from Makefile and genmultilib
++
++# Copyright (C) 2016 Free Software Foundation, Inc.
++#
++# This file is part of GCC.
++#
++# GCC is free software; you can redistribute it and/or modify it under
++# the terms of the GNU General Public License as published by the Free
++# Software Foundation; either version 3, or (at your option) any later
++# version.
++#
++# GCC is distributed in the hope that it will be useful, but WITHOUT ANY
++# WARRANTY; without even the implied warranty of MERCHANTABILITY or
++# FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
++# for more details.
++#
++# You should have received a copy of the GNU General Public License
++# along with GCC; see the file COPYING3.  If not see
++# <http://www.gnu.org/licenses/>.
++
++MULTILIB_OPTIONS = mcpu=em/mcpu=arcem/mcpu=em4/mcpu=em4_dmips/mcpu=em4_fpus/mcpu=em4_fpuda/mcpu=hs/mcpu=archs/mcpu=hs34/mcpu=hs38/mcpu=hs38_linux/mcpu=arc600/mcpu=arc600_norm/mcpu=arc600_mul64/mcpu=arc600_mul32x16/mcpu=arc601/mcpu=arc601_norm/mcpu=arc601_mul64/mcpu=arc601_mul32x16/mcpu=arc700/mcpu=nps400
++
++MULTILIB_DIRNAMES = em arcem em4 em4_dmips em4_fpus em4_fpuda hs archs hs34 hs38 hs38_linux arc600 arc600_norm arc600_mul64 arc600_mul32x16 arc601 arc601_norm arc601_mul64 arc601_mul32x16 arc700 nps400
++
++MULTILIB_REUSE =mcpu.arcem=mcpu.em/mmpy-option.2/mcode-density/mbarrel-shifter
++MULTILIB_REUSE +=mcpu.em4=mcpu.em/mcode-density
++MULTILIB_REUSE +=mcpu.em4_dmips=mcpu.em/mmpy-option.2/mcode-density/mdiv-rem/mnorm/mnorm/mbarrel-shifter
++MULTILIB_REUSE +=mcpu.em4_fpus=mcpu.em/mmpy-option.2/mcode-density/mdiv-rem/mnorm/mnorm/mbarrel-shifter/mfpu.fpus
++MULTILIB_REUSE +=mcpu.em4_fpuda=mcpu.em/mmpy-option.2/mcode-density/mdiv-rem/mnorm/mnorm/mbarrel-shifter/mfpu.fpuda
++MULTILIB_REUSE +=mcpu.archs=mcpu.hs/mmpy-option.2/mdiv-rem/mll64
++MULTILIB_REUSE +=mcpu.hs34=mcpu.hs/mmpy-option.2
++MULTILIB_REUSE +=mcpu.hs38=mcpu.hs/mmpy-option.9/mdiv-rem/mll64
++MULTILIB_REUSE +=mcpu.hs38_linux=mcpu.hs/mmpy-option.9/mdiv-rem/mll64/mfpu.fpud_all
++MULTILIB_REUSE +=mcpu.arc600=mcpu.601/mbarrel-shifter
++MULTILIB_REUSE +=mcpu.arc600_norm=mcpu.601/mbarrel-shifter/mnorm
++MULTILIB_REUSE +=mcpu.arc600_mul64=mcpu.601/mbarrel-shifter/mnorm/mmul64
++MULTILIB_REUSE +=mcpu.arc600_mul32x16=mcpu.601/mbarrel-shifter/mnorm/mmul32x16
++MULTILIB_REUSE +=mcpu.arc601_norm=mcpu.601/mnorm
++MULTILIB_REUSE +=mcpu.arc601_mul64=mcpu.601/mnorm/mmul64
++MULTILIB_REUSE +=mcpu.arc601_mul32x16=mcpu.601/mnorm/mmul32x16
++
++# Aliases:
++MULTILIB_MATCHES  = mcpu?arc600=mcpu?ARC600
++MULTILIB_MATCHES += mcpu?arc600=mARC600
++MULTILIB_MATCHES += mcpu?arc600=mA6
++MULTILIB_MATCHES += mcpu?arc601=mcpu?ARC601
++MULTILIB_MATCHES += mcpu?arc700=mA7
++MULTILIB_MATCHES += mcpu?arc700=mARC700
+diff --git a/gcc/config/arc/t-arc-uClibc b/gcc/config/arc/t-uClibc
+similarity index 100%
+rename from gcc/config/arc/t-arc-uClibc
+rename to gcc/config/arc/t-uClibc
+diff --git a/gcc/doc/invoke.texi b/gcc/doc/invoke.texi
+index e6e725ec1c01..a3fa950d064b 100644
+--- a/gcc/doc/invoke.texi
++++ b/gcc/doc/invoke.texi
+@@ -13230,29 +13230,88 @@ values for @var{cpu} are
+ @table @samp
+ @opindex mA6
+ @opindex mARC600
+- at item ARC600
+ @item arc600
+ Compile for ARC600.  Aliases: @option{-mA6}, @option{-mARC600}.
+ 
+- at item ARC601
+ @item arc601
+ @opindex mARC601
+ Compile for ARC601.  Alias: @option{-mARC601}.
+ 
+- at item ARC700
+ @item arc700
+ @opindex mA7
+ @opindex mARC700
+ Compile for ARC700.  Aliases: @option{-mA7}, @option{-mARC700}.
+ This is the default when configured with @option{--with-cpu=arc700}@.
+ 
+- at item ARCEM
+ @item arcem
+ Compile for ARC EM.
+ 
+- at item ARCHS
+ @item archs
+ Compile for ARC HS.
++
++ at item em
++ at opindex em
++Compile for ARC EM cpu with no hardware extension.
++
++ at item em4
++ at opindex em4
++Compile for ARC EM4 cpu.
++
++ at item em4_dmips
++ at opindex em4_dmips
++Compile for ARC EM4 DMIPS cpu.
++
++ at item em4_fpus
++ at opindex em4_pus
++Compile for ARC EM4 DMIPS cpu with single precision floating point
++extension.
++
++ at item em4_fpuda
++ at opindex em4_fpuda
++Compile for ARC EM4 DMIPS cpu with single precision floating point and
++double assists instructions.
++
++ at item hs
++ at opindex hs
++Compile for ARC HS cpu with no hardware extension, except the atomic
++instructions.
++
++ at item hs34
++ at opindex hs34
++Compile for ARC HS34 cpu.
++
++ at item hs38
++ at opindex hs38
++Compile for ARC HS38 cpu.
++
++ at item hs38_linux
++ at opindex hs38_linux
++Compile for ARC HS38 cpu with all hardware extensions on.
++
++ at item arc600_norm
++ at opindex arc600_norm
++Compile for ARC 600 cpu with norm instruction enabled.
++
++ at item arc600_mul32x16
++ at opindex arc600_mul32x16
++Compile for ARC 600 cpu with norm and mul32x16 instructions enabled.
++
++ at item arc600_mul64
++ at opindex arc600_mul64
++Compile for ARC 600 cpu with norm and mul64 instructions enabled.
++
++ at item arc601_norm
++ at opindex arc601_norm
++Compile for ARC 601 cpu with norm instruction enabled.
++
++ at item arc601_mul32x16
++ at opindex arc601_mul32x16
++Compile for ARC 601 cpu with norm and mul32x16 instructions enabled.
++
++ at item arc601_mul64
++ at opindex arc601_mul64
++Compile for ARC 601 cpu with norm and mul64 instructions enabled.
++
+ @end table
+ 
+ @item -mdpfp
+@@ -13279,7 +13338,8 @@ supported.  This is always enabled for @option{-mcpu=ARC700}.
+ 
+ @item -mno-mpy
+ @opindex mno-mpy
+-Do not generate mpy instructions for ARC700.
++Do not generate mpy instructions for ARC700.  This instruction is
++deprecated.
+ 
+ @item -mmul32x16
+ @opindex mmul32x16
+@@ -13486,12 +13546,14 @@ define preprocessor macro symbols.
+ @item -mdsp-packa
+ @opindex mdsp-packa
+ Passed down to the assembler to enable the DSP Pack A extensions.
+-Also sets the preprocessor symbol @code{__Xdsp_packa}.
++Also sets the preprocessor symbol @code{__Xdsp_packa}.  This option is
++deprecated.
+ 
+ @item -mdvbf
+ @opindex mdvbf
+ Passed down to the assembler to enable the dual viterbi butterfly
+-extension.  Also sets the preprocessor symbol @code{__Xdvbf}.
++extension.  Also sets the preprocessor symbol @code{__Xdvbf}.  This
++option is deprecated.
+ 
+ @c ARC700 4.10 extension instruction
+ @item -mlock
+@@ -13503,19 +13565,19 @@ Conditional extension.  Also sets the preprocessor symbol
+ @item -mmac-d16
+ @opindex mmac-d16
+ Passed down to the assembler.  Also sets the preprocessor symbol
+- at code{__Xxmac_d16}.
++ at code{__Xxmac_d16}.  This option is deprecated.
+ 
+ @item -mmac-24
+ @opindex mmac-24
+ Passed down to the assembler.  Also sets the preprocessor symbol
+- at code{__Xxmac_24}.
++ at code{__Xxmac_24}.  This option is deprecated.
+ 
+ @c ARC700 4.10 extension instruction
+ @item -mrtsc
+ @opindex mrtsc
+ Passed down to the assembler to enable the 64-bit Time-Stamp Counter
+ extension instruction.  Also sets the preprocessor symbol
+- at code{__Xrtsc}.
++ at code{__Xrtsc}.  This option is deprecated.
+ 
+ @c ARC700 4.10 extension instruction
+ @item -mswape
+@@ -13528,7 +13590,7 @@ extension instruction.  Also sets the preprocessor symbol
+ @opindex mtelephony
+ Passed down to the assembler to enable dual and single operand
+ instructions for telephony.  Also sets the preprocessor symbol
+- at code{__Xtelephony}.
++ at code{__Xtelephony}.  This option is deprecated.
+ 
+ @item -mxy
+ @opindex mxy
+-- 
+2.7.4
+
diff --git a/toolchain/gcc/patches/6.3.0/0023-ARC-Various-small-miscellaneous-fixes.patch b/toolchain/gcc/patches/6.3.0/0023-ARC-Various-small-miscellaneous-fixes.patch
new file mode 100644
index 0000000..2853698
--- /dev/null
+++ b/toolchain/gcc/patches/6.3.0/0023-ARC-Various-small-miscellaneous-fixes.patch
@@ -0,0 +1,243 @@
+From 7659e01377a3f5bbfbce653f59e0a67538fe25d1 Mon Sep 17 00:00:00 2001
+From: Claudiu Zissulescu <claziss at synopsys.com>
+Date: Wed, 4 May 2016 17:33:42 +0200
+Subject: [PATCH 23/89] [ARC] Various small miscellaneous fixes.
+
+gcc/
+2016-05-09  Claudiu Zissulescu  <claziss at synopsys.com>
+
+	* config/arc/arc.md (movsi_insn): Disable unsupported move
+	instructions for ARCv2 cores.
+	* config/arc/arc.h (SHIFT_COUNT_TRUNCATED): Define to one.
+	(LINK_COMMAND_SPEC): Remove.
+---
+ gcc/config/arc/arc.c          |  5 +----
+ gcc/config/arc/arc.h          | 27 +++------------------------
+ gcc/config/arc/arc.md         | 35 +++++++++++++++++++----------------
+ gcc/config/arc/constraints.md |  3 ++-
+ gcc/config/arc/fpu.md         |  4 +++-
+ gcc/config/arc/fpx.md         | 26 ++++++++++++--------------
+ 6 files changed, 40 insertions(+), 60 deletions(-)
+
+diff --git a/gcc/config/arc/arc.c b/gcc/config/arc/arc.c
+index 985df8151d74..0830af3cbef6 100644
+--- a/gcc/config/arc/arc.c
++++ b/gcc/config/arc/arc.c
+@@ -9025,10 +9025,7 @@ arc_process_double_reg_moves (rtx *operands)
+       rtx srcLow  = simplify_gen_subreg (SImode, src, DFmode,
+ 					TARGET_BIG_ENDIAN ? 4 : 0);
+ 
+-      emit_insn (gen_rtx_UNSPEC_VOLATILE (Pmode,
+-					  gen_rtvec (3, dest, srcHigh, srcLow),
+-					  VUNSPEC_ARC_DEXCL_NORES));
+-
++      emit_insn (gen_dexcl_2op (dest, srcHigh, srcLow));
+     }
+   else
+     gcc_unreachable ();
+diff --git a/gcc/config/arc/arc.h b/gcc/config/arc/arc.h
+index f1705d587d2f..f8f195d70153 100644
+--- a/gcc/config/arc/arc.h
++++ b/gcc/config/arc/arc.h
+@@ -124,24 +124,6 @@ extern const char *arc_cpu_to_as (int argc, const char **argv);
+ 		   %{!marclinux*: %{pg|p|profile:-marclinux_prof;: -marclinux}} \
+ 		   %{!z:-z max-page-size=0x2000 -z common-page-size=0x2000} \
+ 		   %{shared:-shared}"
+-/* Like the standard LINK_COMMAND_SPEC, but add %G when building
+-   a shared library with -nostdlib, so that the hidden functions of libgcc
+-   will be incorporated.
+-   N.B., we don't want a plain -lgcc, as this would lead to re-exporting
+-   non-hidden functions, so we have to consider libgcc_s.so.* first, which in
+-   turn should be wrapped with --as-needed.  */
+-#define LINK_COMMAND_SPEC "\
+-%{!fsyntax-only:%{!c:%{!M:%{!MM:%{!E:%{!S:\
+-    %(linker) %l " LINK_PIE_SPEC "%X %{o*} %{A} %{d} %{e*} %{m} %{N} %{n} %{r}\
+-    %{s} %{t} %{u*} %{x} %{z} %{Z} %{!A:%{!nostdlib:%{!nostartfiles:%S}}}\
+-    %{static:} %{L*} %(mfwrap) %(link_libgcc) %o\
+-    %{fopenacc|fopenmp|%:gt(%{ftree-parallelize-loops=*:%*} 1):\
+-	%:include(libgomp.spec)%(link_gomp)}\
+-    %(mflib)\
+-    %{fprofile-arcs|fprofile-generate|coverage:-lgcov}\
+-    %{!nostdlib:%{!nodefaultlibs:%(link_ssp) %(link_gcc_c_sequence)}}\
+-    %{!A:%{!nostdlib:%{!nostartfiles:%E}}} %{T*} }}}}}}"
+-
+ #else
+ #define LINK_SPEC "%{mbig-endian:-EB} %{EB} %{EL}\
+   %{pg|p:-marcelf_prof;mA7|mARC700|mcpu=arc700|mcpu=ARC700: -marcelf}"
+@@ -1563,13 +1545,10 @@ extern int arc_return_address_regs[4];
+ /* Undo the effects of the movmem pattern presence on STORE_BY_PIECES_P .  */
+ #define MOVE_RATIO(SPEED) ((SPEED) ? 15 : 3)
+ 
+-/* Define this to be nonzero if shift instructions ignore all but the low-order
+-   few bits. Changed from 1 to 0 for rotate pattern testcases
+-   (e.g. 20020226-1.c). This change truncates the upper 27 bits of a word
+-   while rotating a word. Came to notice through a combine phase
+-   optimization viz. a << (32-b) is equivalent to a << (-b).
++/* Define this to be nonzero if shift instructions ignore all but the
++   low-order few bits.
+ */
+-#define SHIFT_COUNT_TRUNCATED 0
++#define SHIFT_COUNT_TRUNCATED 1
+ 
+ /* Value is 1 if truncating an integer of INPREC bits to OUTPREC bits
+    is done just by pretending it is already truncated.  */
+diff --git a/gcc/config/arc/arc.md b/gcc/config/arc/arc.md
+index 5accf4a479b4..c86fc02c8240 100644
+--- a/gcc/config/arc/arc.md
++++ b/gcc/config/arc/arc.md
+@@ -699,9 +699,9 @@
+ ; the iscompact attribute allows the epilogue expander to know for which
+ ; insns it should lengthen the return insn.
+ ; N.B. operand 1 of alternative 7 expands into pcl,symbol at gotpc .
+-(define_insn "*movsi_insn"                      ;   0     1     2    3  4 5   6   7   8   9   10  11  12    13   14  15  16     17     18 19   20    21    22 23 24    25 26  27   28   29
+-  [(set (match_operand:SI 0 "move_dest_operand" "=Rcq,Rcq#q,    w,   h, w,w,  w,  w,  w,  w,???w, ?w,  w,Rcq#q,   w,Rcq,  S,   Us<,RcqRck,!*x,  r,!*Rsd,!*Rcd,r,Ucm,  Usd,m,???m,VUsc,VUsc")
+-	(match_operand:SI 1 "move_src_operand"  "  cL,   cP,Rcq#q,hCm1,cL,I,Crr,Clo,Chi,Cbi,?Rac,Cpc,Clb, ?Cal,?Cal,  T,Rcq,RcqRck,   Us>,Usd,Ucm,  Usd,  Ucd,m,  w,!*Rzd,c,?Rac, Cm3, C32"))]
++(define_insn "*movsi_insn"                      ;   0     1     2     3  4 5   6   7   8   9   10  11  12    13   14  15  16     17     18 19   20    21    22 23 24    25 26  27   28   29
++  [(set (match_operand:SI 0 "move_dest_operand" "=Rcq,Rcq#q,    w,    h, w,w,  w,  w,  w,  w,???w, ?w,  w,Rcq#q,   w,Rcq,  S,   Us<,RcqRck,!*x,  r,!*Rsd,!*Rcd,r,Ucm,  Usd,m,???m,VUsc,VUsc")
++	(match_operand:SI 1 "move_src_operand"  "  cL,   cP,Rcq#q,hPCm1,cL,I,Crr,Clo,Chi,Cbi,?Rac,Cpc,Clb, ?Cal,?Cal,  T,Rcq,RcqRck,   Us>,Usd,Ucm,  Usd,  Ucd,m,  w,!*Rzd,c,?Rac, Cm3, C32"))]
+   "register_operand (operands[0], SImode)
+    || register_operand (operands[1], SImode)
+    || (CONSTANT_P (operands[1])
+@@ -746,7 +746,7 @@
+    ; of Crr to 4.
+    (set_attr "length" "*,*,*,*,4,4,4,4,4,4,4,8,8,*,8,*,*,*,*,*,4,*,4,*,*,*,*,*,4,8")
+    (set_attr "predicable" "yes,no,yes,no,yes,no,no,no,no,no,yes,no,no,yes,yes,no,no,no,no,no,no,no,no,no,no,no,no,no,no,no")
+-   (set_attr "cpu_facility" "*,*,av1,av2,*,*,*,*,*,*,*,*,*,*,*,*,*,*,*,*,*,av2,av2,*,*,av2,*,*,av2,*")])
++   (set_attr "cpu_facility" "av1,av1,av1,av2,*,*,*,*,*,*,*,*,*,*,*,*,*,*,*,*,*,av2,av2,*,*,av2,*,*,av2,*")])
+ 
+ ;; Sometimes generated by the epilogue code.  We don't want to
+ ;; recognize these addresses in general, because the limm is costly,
+@@ -1083,12 +1083,9 @@
+ 	(match_operand:DI 1 "general_operand" ""))]
+   ""
+   "
+-{
+-  /* Everything except mem = const or mem = mem can be done easily.  */
+-
+-  if (GET_CODE (operands[0]) == MEM)
+-    operands[1] = force_reg (DImode, operands[1]);
+-}")
++  if (prepare_move_operands (operands, DImode))
++    DONE;
++  ")
+ 
+ (define_insn_and_split "*movdi_insn"
+   [(set (match_operand:DI 0 "move_dest_operand"      "=w, w,r,m")
+@@ -1135,7 +1132,7 @@
+ ;; Floating point move insns.
+ 
+ (define_expand "movsf"
+-  [(set (match_operand:SF 0 "general_operand" "")
++  [(set (match_operand:SF 0 "move_dest_operand" "")
+ 	(match_operand:SF 1 "general_operand" ""))]
+   ""
+   "if (prepare_move_operands (operands, SFmode)) DONE;")
+@@ -1156,7 +1153,7 @@
+    (set_attr "iscompact" "true,false,false,false,false")])
+ 
+ (define_expand "movdf"
+-  [(set (match_operand:DF 0 "nonimmediate_operand" "")
++  [(set (match_operand:DF 0 "move_dest_operand" "")
+ 	(match_operand:DF 1 "general_operand" ""))]
+   ""
+   "if (prepare_move_operands (operands, DFmode)) DONE;")
+@@ -1226,12 +1223,18 @@
+     ; second time to put back the contents which the first DEXCLx
+     ; will have overwritten
+     ; dexcl2 r0, r1, r0
+-    (set (match_dup 4) ; aka r0result
+-     	 ; aka DF, r1, r0
+-	 (unspec_volatile:SI [(match_dup 1) (match_dup 5) (match_dup 4)] VUNSPEC_ARC_DEXCL ))
++    (parallel [
++	       (set (match_dup 4) ; aka r0result
++				  ; aka DF, r1, r0
++		    (unspec_volatile:SI [(match_dup 5) (match_dup 4)]
++					VUNSPEC_ARC_DEXCL))
++	       (clobber (match_dup 1))
++	       ])
+     ; Generate the second, which makes sure operand5 and operand4 values
+     ; are put back in the Dx register properly.
+-    (unspec_volatile:SI [(match_dup 1) (match_dup 5) (match_dup 4)] VUNSPEC_ARC_DEXCL_NORES )
++    (set (match_dup 1) (unspec_volatile:DF
++			[(match_dup 5) (match_dup 4)]
++			VUNSPEC_ARC_DEXCL_NORES))
+ 
+     ; Note: we cannot use a (clobber (match_scratch)) here because
+     ; the combine pass will end up replacing uses of it with 0
+diff --git a/gcc/config/arc/constraints.md b/gcc/config/arc/constraints.md
+index b7bf2d39c4e8..8eccb2fdfe37 100644
+--- a/gcc/config/arc/constraints.md
++++ b/gcc/config/arc/constraints.md
+@@ -256,7 +256,8 @@
+  "@internal
+   constant for a highpart that can be checked with a shift (asr.f 0,rn,m)"
+   (and (match_code "const_int")
+-       (match_test "IS_POWEROF2_P (-ival)")))
++       (match_test "IS_POWEROF2_P (-ival)")
++       (match_test "TARGET_BARREL_SHIFTER")))
+ 
+ (define_constraint "Clo"
+  "@internal
+diff --git a/gcc/config/arc/fpu.md b/gcc/config/arc/fpu.md
+index 9b0a65d93863..1050cabef62d 100644
+--- a/gcc/config/arc/fpu.md
++++ b/gcc/config/arc/fpu.md
+@@ -197,7 +197,9 @@
+   [(set (match_operand:SF 0 "register_operand"         "=r,r,r,r,r")
+ 	(div:SF (match_operand:SF 1 "nonmemory_operand" "0,r,0,r,F")
+ 		(match_operand:SF 2 "nonmemory_operand" "r,r,F,F,r")))]
+-  "TARGET_FP_SP_SQRT"
++  "TARGET_FP_SP_SQRT
++   && (register_operand (operands[1], SFmode)
++       || register_operand (operands[2], SFmode))"
+   "fsdiv%? %0,%1,%2"
+   [(set_attr "length" "4,4,8,8,8")
+    (set_attr "iscompact" "false")
+diff --git a/gcc/config/arc/fpx.md b/gcc/config/arc/fpx.md
+index 2e11157cabfb..9ed2b7c683ab 100644
+--- a/gcc/config/arc/fpx.md
++++ b/gcc/config/arc/fpx.md
+@@ -168,28 +168,26 @@
+ (set_attr "type" "lr")]
+ )
+ 
+-
+ (define_insn "*dexcl_3op_peep2_insn"
+   [(set (match_operand:SI 0 "dest_reg_operand" "=r") ; not register_operand, to accept SUBREG
+-		   (unspec_volatile:SI [
+-		   			(match_operand:DF 1 "arc_double_register_operand" "D")
+-					(match_operand:SI 2 "shouldbe_register_operand" "r")  ; r1
+-					(match_operand:SI 3 "shouldbe_register_operand" "r") ; r0
+-					] VUNSPEC_ARC_DEXCL ))
+-  ]
++	(unspec_volatile:SI
++	 [(match_operand:SI 1 "shouldbe_register_operand" "r") ; r1
++	  (match_operand:SI 2 "shouldbe_register_operand" "r") ; r0
++	  ] VUNSPEC_ARC_DEXCL ))
++   (clobber (match_operand:DF 3 "arc_double_register_operand" "=&D"))]
+   "TARGET_DPFP"
+-  "dexcl%F1 %0, %2, %3"
++  "dexcl%F3 %0, %1, %2"
+   [(set_attr "type" "move")
+    (set_attr "length" "4")]
+ )
+ 
+ ;; version which will not overwrite operand0
+-(define_insn "*dexcl_3op_peep2_insn_nores"
+-  [   (unspec_volatile:SI [
+-		   			(match_operand:DF 0 "arc_double_register_operand" "D")
+-					(match_operand:SI 1 "shouldbe_register_operand" "r")  ; r1
+-					(match_operand:SI 2 "shouldbe_register_operand" "r") ; r0
+-					] VUNSPEC_ARC_DEXCL_NORES )
++(define_insn "dexcl_2op"
++  [(set (match_operand:DF 0 "arc_double_register_operand" "=D")
++	(unspec_volatile:DF
++	 [(match_operand:SI 1 "shouldbe_register_operand" "r") ; r1
++	  (match_operand:SI 2 "shouldbe_register_operand" "r") ; r0
++	  ] VUNSPEC_ARC_DEXCL_NORES))
+   ]
+   "TARGET_DPFP"
+   "dexcl%F0 0, %1, %2"
+-- 
+2.7.4
+
diff --git a/toolchain/gcc/patches/6.3.0/0024-ARC-Disable-compact-casesi-patterns-for-arcv2.patch b/toolchain/gcc/patches/6.3.0/0024-ARC-Disable-compact-casesi-patterns-for-arcv2.patch
new file mode 100644
index 0000000..3e2f077
--- /dev/null
+++ b/toolchain/gcc/patches/6.3.0/0024-ARC-Disable-compact-casesi-patterns-for-arcv2.patch
@@ -0,0 +1,50 @@
+From 0f8cd686af4d8a438334fec2ea54a0828aa80d7c Mon Sep 17 00:00:00 2001
+From: Claudiu Zissulescu <claziss at synopsys.com>
+Date: Wed, 4 May 2016 17:34:25 +0200
+Subject: [PATCH 24/89] [ARC] Disable compact casesi patterns for arcv2
+
+gcc/
+2016-05-09  Claudiu Zissulescu  <claziss at synopsys.com>
+
+	* common/config/arc/arc-common.c (arc_option_optimization_table):
+	Remove compact casesi option.
+	* config/arc/arc.c (arc_override_options): Use compact casesi
+	option only for pre-ARCv2 cores.
+---
+ gcc/common/config/arc/arc-common.c | 1 -
+ gcc/config/arc/arc.c               | 7 +++++++
+ 2 files changed, 7 insertions(+), 1 deletion(-)
+
+diff --git a/gcc/common/config/arc/arc-common.c b/gcc/common/config/arc/arc-common.c
+index 0141e3d6a23c..289886006380 100644
+--- a/gcc/common/config/arc/arc-common.c
++++ b/gcc/common/config/arc/arc-common.c
+@@ -57,7 +57,6 @@ static const struct default_options arc_option_optimization_table[] =
+     { OPT_LEVELS_ALL, OPT_mbbit_peephole, NULL, 1 },
+     { OPT_LEVELS_SIZE, OPT_mq_class, NULL, 1 },
+     { OPT_LEVELS_SIZE, OPT_mcase_vector_pcrel, NULL, 1 },
+-    { OPT_LEVELS_SIZE, OPT_mcompact_casesi, NULL, 1 },
+     { OPT_LEVELS_NONE, 0, NULL, 0 }
+   };
+ 
+diff --git a/gcc/config/arc/arc.c b/gcc/config/arc/arc.c
+index 0830af3cbef6..93c8841a1b2b 100644
+--- a/gcc/config/arc/arc.c
++++ b/gcc/config/arc/arc.c
+@@ -876,6 +876,13 @@ arc_override_options (void)
+   if (arc_size_opt_level == 3)
+     optimize_size = 1;
+ 
++  /* Compact casesi is not a valid option for ARCv2 family, disable
++     it.  */
++  if (TARGET_V2)
++    TARGET_COMPACT_CASESI = 0;
++  else if (optimize_size == 1)
++    TARGET_COMPACT_CASESI = 1;
++
+   if (flag_pic)
+     target_flags |= MASK_NO_SDATA_SET;
+ 
+-- 
+2.7.4
+
diff --git a/toolchain/gcc/patches/6.3.0/0025-ARC-Add-support-for-QuarkSE-processor.patch b/toolchain/gcc/patches/6.3.0/0025-ARC-Add-support-for-QuarkSE-processor.patch
new file mode 100644
index 0000000..1908141
--- /dev/null
+++ b/toolchain/gcc/patches/6.3.0/0025-ARC-Add-support-for-QuarkSE-processor.patch
@@ -0,0 +1,429 @@
+From 6e34de3cf703f1db5c7aef2a47c6c86c0602cf26 Mon Sep 17 00:00:00 2001
+From: Claudiu Zissulescu <claziss at synopsys.com>
+Date: Wed, 25 May 2016 14:59:41 +0200
+Subject: [PATCH 25/89] [ARC] Add support for QuarkSE processor.
+
+gcc/
+2016-05-25  Claudiu Zissulescu  <claziss at synopsys.com>
+
+	* config/arc/arc-arches.def: Add FPX quarkse instruction as valid
+	for arcem.
+	* config/arc/arc-c.def (__ARC_FPX_QUARK__): Define.
+	* config/arc/arc-cpus.def (quarkse_em): Add.
+	* config/arc/arc-options.def (FL_FPX_QUARK, FL_QUARK): Likewise.
+	* config/arc/arc-opts.h (FPX_QK): Define.
+	* config/arc/arc-tables.opt: Regenerate.
+	* config/arc/arc.c (gen_compare_reg): Change.
+	(arc_register_move_cost): Avoid Dy,Dx moves.
+	* config/arc/arc.h (TARGET_HARD_FLOAT): Change.
+	(TARGET_FPX_QUARK, TARGET_FP_ASSIST): Define.
+	* config/arc/arc.md (divsf3, sqrtsf2, fix_truncsfsi2, floatsisf2):
+	New expands.
+	* config/arc/fpu.md (divsf3_fpu, sqrtsf2_fpu, floatsisf2_fpu)
+	(fix_truncsfsi2_fpu): Rename.
+	* config/arc/fpx.md (cmp_quark, cmpsf_quark_, cmpsf_quark_ord)
+	(cmpsf_quark_uneq, cmpsf_quark_eq, divsf3_quark, sqrtsf2_quark)
+	(fix_truncsfsi2_quark, floatsisf2_quark): New patterns.
+	* config/arc/t-multilib: Regenerate.
+---
+ gcc/config/arc/arc-arches.def  |  2 +-
+ gcc/config/arc/arc-c.def       |  1 +
+ gcc/config/arc/arc-cpus.def    |  1 +
+ gcc/config/arc/arc-options.def |  2 +
+ gcc/config/arc/arc-opts.h      |  2 +
+ gcc/config/arc/arc-tables.opt  |  3 ++
+ gcc/config/arc/arc.c           | 22 +++++++++-
+ gcc/config/arc/arc.h           | 12 +++--
+ gcc/config/arc/arc.md          | 46 ++++++++++++++++++++
+ gcc/config/arc/fpu.md          |  8 ++--
+ gcc/config/arc/fpx.md          | 99 ++++++++++++++++++++++++++++++++++++++++++
+ gcc/config/arc/t-multilib      |  5 ++-
+ 12 files changed, 188 insertions(+), 15 deletions(-)
+
+diff --git a/gcc/config/arc/arc-arches.def b/gcc/config/arc/arc-arches.def
+index da69a1a8230c..db96ce1241cb 100644
+--- a/gcc/config/arc/arc-arches.def
++++ b/gcc/config/arc/arc-arches.def
+@@ -19,7 +19,7 @@
+ 
+ ARC_ARCH("arcem", em, FL_MPYOPT_1_6 | FL_DIVREM | FL_CD | FL_NORM	\
+ 	 | FL_BS | FL_SWAP | FL_FPUS | FL_SPFP | FL_DPFP		\
+-	 | FL_SIMD | FL_FPUDA, 0)
++	 | FL_SIMD | FL_FPUDA | FL_QUARK, 0)
+ ARC_ARCH("archs", hs, FL_MPYOPT_7_9 | FL_DIVREM | FL_NORM | FL_CD	\
+ 	 | FL_ATOMIC | FL_LL64 | FL_BS | FL_SWAP			\
+ 	 | FL_FPUS | FL_FPUD,						\
+diff --git a/gcc/config/arc/arc-c.def b/gcc/config/arc/arc-c.def
+index 4cfd7b6e35fd..fd643760d88e 100644
+--- a/gcc/config/arc/arc-c.def
++++ b/gcc/config/arc/arc-c.def
+@@ -58,6 +58,7 @@ ARC_C_DEF ("__ARC_FPU_DP_DIV__", TARGET_FP_DP_SQRT)
+ ARC_C_DEF ("__ARC_FPU_SP_FMA__", TARGET_FP_SP_FUSED)
+ ARC_C_DEF ("__ARC_FPU_DP_FMA__", TARGET_FP_DP_FUSED)
+ ARC_C_DEF ("__ARC_FPU_ASSIST__", TARGET_FP_DP_AX)
++ARC_C_DEF ("__ARC_FPX_QUARK__",  TARGET_FPX_QUARK)
+ 
+ /* To be deprecated.  */
+ ARC_C_DEF ("__A6__",     TARGET_ARC600)
+diff --git a/gcc/config/arc/arc-cpus.def b/gcc/config/arc/arc-cpus.def
+index 6d93c89e04a4..8782bd5e9263 100644
+--- a/gcc/config/arc/arc-cpus.def
++++ b/gcc/config/arc/arc-cpus.def
+@@ -23,6 +23,7 @@ ARC_CPU (em4,       em, FL_CD, NONE)
+ ARC_CPU (em4_dmips, em, FL_MPYOPT_2|FL_CD|FL_DIVREM|FL_NORM|FL_SWAP|FL_BS, NONE)
+ ARC_CPU (em4_fpus,  em, FL_MPYOPT_2|FL_CD|FL_DIVREM|FL_NORM|FL_SWAP|FL_BS|FL_FPU_FPUS, NONE)
+ ARC_CPU (em4_fpuda, em, FL_MPYOPT_2|FL_CD|FL_DIVREM|FL_NORM|FL_SWAP|FL_BS|FL_FPU_FPUDA, NONE)
++ARC_CPU (quarkse_em, em, FL_MPYOPT_3|FL_CD|FL_DIVREM|FL_NORM|FL_SWAP|FL_BS|FL_FPX_QUARK|FL_SPFP|FL_DPFP, NONE)
+ 
+ ARC_CPU (hs,         hs, 0, NONE)
+ ARC_CPU (archs,      hs, FL_MPYOPT_2|FL_DIVREM|FL_LL64, NONE)
+diff --git a/gcc/config/arc/arc-options.def b/gcc/config/arc/arc-options.def
+index 3834894a0884..778f69d95afe 100644
+--- a/gcc/config/arc/arc-options.def
++++ b/gcc/config/arc/arc-options.def
+@@ -59,10 +59,12 @@ ARC_OPTX (FL_FPU_FPUD,	    (1ULL << 34), arc_fpu_build, FPU_FPUD,	"mfpu=fpud")
+ ARC_OPTX (FL_FPU_FPUD_DIV,  (1ULL << 35), arc_fpu_build, FPU_FPUD_DIV,	"mfpu=fpud_div")
+ ARC_OPTX (FL_FPU_FPUD_FMA,  (1ULL << 36), arc_fpu_build, FPU_FPUD_FMA,	"mfpu=fpud_fma")
+ ARC_OPTX (FL_FPU_FPUD_ALL,  (1ULL << 37), arc_fpu_build, FPU_FPUD_ALL,	"mfpu=fpud_all")
++ARC_OPTX (FL_FPX_QUARK,	    (1ULL << 38), arc_fpu_build, FPX_QK,	"quarkse fp")
+ 
+ ARC_OPT (FL_FPUS,  (0xFULL << 26), 0, "single precission floating point")
+ ARC_OPT (FL_FPUDA, (0xFFULL << 26), 0, "double precission fp assist")
+ ARC_OPT (FL_FPUD,  (0xF0FULL << 26), 0, "double precission floating point")
++ARC_OPT (FL_QUARK, (1ULL << 38), 0, "Quark SE fp extension")
+ 
+ /* Local Variables: */
+ /* mode: c */
+diff --git a/gcc/config/arc/arc-opts.h b/gcc/config/arc/arc-opts.h
+index 81446b4a412a..819b97c299f6 100644
+--- a/gcc/config/arc/arc-opts.h
++++ b/gcc/config/arc/arc-opts.h
+@@ -48,6 +48,8 @@ enum processor_type
+ #define FPU_DD    0x0080
+ /* Double precision floating point assist operations.  */
+ #define FPX_DP    0x0100
++/* Quark SE floating point instructions.  */
++#define FPX_QK    0x0200
+ 
+ /* fpus option combi.  */
+ #define FPU_FPUS  (FPU_SP | FPU_SC)
+diff --git a/gcc/config/arc/arc-tables.opt b/gcc/config/arc/arc-tables.opt
+index 0e7c50c7be78..41e325c91d57 100644
+--- a/gcc/config/arc/arc-tables.opt
++++ b/gcc/config/arc/arc-tables.opt
+@@ -43,6 +43,9 @@ EnumValue
+ Enum(processor_type) String(em4_fpuda) Value(PROCESSOR_em4_fpuda)
+ 
+ EnumValue
++Enum(processor_type) String(quarkse_em) Value(PROCESSOR_quarkse_em)
++
++EnumValue
+ Enum(processor_type) String(hs) Value(PROCESSOR_hs)
+ 
+ EnumValue
+diff --git a/gcc/config/arc/arc.c b/gcc/config/arc/arc.c
+index 93c8841a1b2b..c2673334db5d 100644
+--- a/gcc/config/arc/arc.c
++++ b/gcc/config/arc/arc.c
+@@ -1728,6 +1728,26 @@ gen_compare_reg (rtx comparison, machine_mode omode)
+ 						 gen_rtx_REG (CC_FPXmode, 61),
+ 						 const0_rtx)));
+     }
++  else if (TARGET_FPX_QUARK && (cmode == SFmode))
++    {
++      switch (code)
++	{
++	case NE: case EQ: case GT: case UNLE: case GE: case UNLT:
++	case UNEQ: case LTGT: case ORDERED: case UNORDERED:
++	  break;
++	case LT: case UNGE: case LE: case UNGT:
++	  code = swap_condition (code);
++	  tmp = x;
++	  x = y;
++	  y = tmp;
++	  break;
++	default:
++	  gcc_unreachable ();
++	}
++
++      emit_insn (gen_cmp_quark (cc_reg,
++				gen_rtx_COMPARE (mode, x, y)));
++    }
+   else if (TARGET_HARD_FLOAT
+ 	   && ((cmode == SFmode && TARGET_FP_SP_BASE)
+ 	       || (cmode == DFmode && TARGET_FP_DP_BASE)))
+@@ -7282,7 +7302,7 @@ arc_register_move_cost (machine_mode,
+     return 8;
+ 
+   /* Force an attempt to 'mov Dy,Dx' to spill.  */
+-  if (TARGET_ARC700 && TARGET_DPFP
++  if ((TARGET_ARC700 || TARGET_EM) && TARGET_DPFP
+       && from_class == DOUBLE_REGS && to_class == DOUBLE_REGS)
+     return 100;
+ 
+diff --git a/gcc/config/arc/arc.h b/gcc/config/arc/arc.h
+index f8f195d70153..795831d2c810 100644
+--- a/gcc/config/arc/arc.h
++++ b/gcc/config/arc/arc.h
+@@ -197,12 +197,7 @@ extern const char *arc_cpu_to_as (int argc, const char **argv);
+    default for A7, and only for pre A7 cores when -mnorm is given.  */
+ #define TARGET_NORM (TARGET_ARC700 || TARGET_NORM_SET || TARGET_HS)
+ /* Indicate if an optimized floating point emulation library is available.  */
+-#define TARGET_OPTFPE				\
+-   (TARGET_ARC700				\
+-    /* We need a barrel shifter and NORM.  */	\
+-    || (TARGET_ARC600 && TARGET_NORM_SET)	\
+-    || TARGET_HS				\
+-    || (TARGET_EM && TARGET_NORM_SET && TARGET_BARREL_SHIFTER))
++#define TARGET_OPTFPE (TARGET_ARC700 || TARGET_FPX_QUARK)
+ 
+ /* Non-zero means the cpu supports swap instruction.  This flag is set by
+    default for A7, and only for pre A7 cores when -mswap is given.  */
+@@ -1704,7 +1699,7 @@ enum
+ 
+ /* FPU defines.  */
+ /* Any FPU support.  */
+-#define TARGET_HARD_FLOAT (arc_fpu_build != 0)
++#define TARGET_HARD_FLOAT   ((arc_fpu_build & (FPU_SP | FPU_DP)) != 0)
+ /* Single precision floating point support.  */
+ #define TARGET_FP_SP_BASE   ((arc_fpu_build & FPU_SP) != 0)
+ /* Double precision floating point support.  */
+@@ -1723,5 +1718,8 @@ enum
+ #define TARGET_FP_DP_SQRT   ((arc_fpu_build & FPU_DD) != 0)
+ /* Double precision floating point assist instruction support.  */
+ #define TARGET_FP_DP_AX     ((arc_fpu_build & FPX_DP) != 0)
++/* Custom FP instructions used by QuarkSE EM cpu.  */
++#define TARGET_FPX_QUARK    (TARGET_EM && TARGET_SPFP		\
++			     && (arc_fpu_build == FPX_QK))
+ 
+ #endif /* GCC_ARC_H */
+diff --git a/gcc/config/arc/arc.md b/gcc/config/arc/arc.md
+index c86fc02c8240..87e6a172a9a5 100644
+--- a/gcc/config/arc/arc.md
++++ b/gcc/config/arc/arc.md
+@@ -5983,6 +5983,52 @@
+    gcc_unreachable ();
+  ")
+ 
++;;div
++(define_expand "divsf3"
++  [(set (match_operand:SF 0 "register_operand"        "")
++	(div:SF (match_operand:SF 1 "nonmemory_operand" "")
++		(match_operand:SF 2 "nonmemory_operand" "")))]
++  "TARGET_FPX_QUARK || TARGET_FP_SP_SQRT"
++  "
++  if (TARGET_FPX_QUARK)
++   {
++     operands[1] = force_reg (SFmode, operands[1]);
++     operands[2] = force_reg (SFmode, operands[2]);
++   }
++  else
++   {
++     if (!register_operand (operands[1], SFmode)
++        && !register_operand (operands[2], SFmode))
++       operands[1] = force_reg (SFmode, operands[1]);
++   }
++  ")
++
++;; Square root
++(define_expand "sqrtsf2"
++  [(set (match_operand:SF 0 "register_operand"           "")
++	(sqrt:SF (match_operand:SF 1 "nonmemory_operand" "")))]
++  "TARGET_FPX_QUARK || TARGET_FP_SP_SQRT"
++  "
++  if (TARGET_FPX_QUARK)
++   {
++     operands[1] = force_reg (SFmode, operands[1]);
++   }
++")
++
++;; SF->SI (using rounding towards zero)
++(define_expand "fix_truncsfsi2"
++  [(set (match_operand:SI 0 "register_operand"                "")
++	(fix:SI (fix:SF (match_operand:SF 1 "register_operand" ""))))]
++  "TARGET_FPX_QUARK || TARGET_FP_SP_CONV"
++  "")
++
++;; SI->SF
++(define_expand "floatsisf2"
++  [(set (match_operand:SF 0 "register_operand"            "")
++	(float:SF (match_operand:SI 1 "register_operand" "")))]
++  "TARGET_FPX_QUARK || TARGET_FP_SP_CONV"
++  "")
++
+ (define_expand "extzv"
+   [(set (match_operand:SI 0 "register_operand" "")
+ 	(zero_extract:SI (match_operand:SI 1 "register_operand" "")
+diff --git a/gcc/config/arc/fpu.md b/gcc/config/arc/fpu.md
+index 1050cabef62d..cc7902b568b9 100644
+--- a/gcc/config/arc/fpu.md
++++ b/gcc/config/arc/fpu.md
+@@ -193,7 +193,7 @@
+    (set_attr "type" "fpu")])
+ 
+ ;; Division
+-(define_insn "divsf3"
++(define_insn "divsf3_fpu"
+   [(set (match_operand:SF 0 "register_operand"         "=r,r,r,r,r")
+ 	(div:SF (match_operand:SF 1 "nonmemory_operand" "0,r,0,r,F")
+ 		(match_operand:SF 2 "nonmemory_operand" "r,r,F,F,r")))]
+@@ -215,7 +215,7 @@
+ ;; see pattern in arc.md
+ 
+ ;; Square root
+-(define_insn "sqrtsf2"
++(define_insn "sqrtsf2_fpu"
+   [(set (match_operand:SF 0 "register_operand"           "=r,r")
+ 	(sqrt:SF (match_operand:SF 1 "nonmemory_operand"  "r,F")))]
+   "TARGET_FP_SP_SQRT"
+@@ -412,7 +412,7 @@
+ )
+ 
+ ;; SI->SF
+-(define_insn "floatsisf2"
++(define_insn "floatsisf2_fpu"
+   [(set (match_operand:SF 0 "register_operand"           "=r,r")
+ 	(float:SF (match_operand:SI 1 "register_operand"  "0,r")))]
+   "TARGET_FP_SP_CONV"
+@@ -448,7 +448,7 @@
+ )
+ 
+ ;; SF->SI (using rounding towards zero)
+-(define_insn "fix_truncsfsi2"
++(define_insn "fix_truncsfsi2_fpu"
+   [(set (match_operand:SI 0 "register_operand"                "=r,r")
+ 	(fix:SI (fix:SF (match_operand:SF 1 "register_operand" "0,r"))))]
+   "TARGET_FP_SP_CONV"
+diff --git a/gcc/config/arc/fpx.md b/gcc/config/arc/fpx.md
+index 9ed2b7c683ab..094319e1ce4f 100644
+--- a/gcc/config/arc/fpx.md
++++ b/gcc/config/arc/fpx.md
+@@ -614,3 +614,102 @@
+  [(set_attr "type" "dpfp_addsub")
+   (set_attr "length" "4,8,4,8")
+   (set_attr "cpu_facility" "*,*,fpx,fpx")])
++
++;; Intel QUARK SE extensions
++(define_mode_iterator QUARK_CMP [CC_FP_GT CC_FP_GE])
++(define_mode_attr quark_cmp [(CC_FP_GT "gt") (CC_FP_GE "ge")])
++
++(define_expand "cmp_quark"
++  [(parallel [(set (match_operand 0 "")
++		   (match_operand 1 ""))
++	      (clobber (match_scratch:SI 2 ""))])]
++  ""
++  "")
++
++(define_insn "*cmpsf_quark_<quark_cmp>"
++  [(set (reg:QUARK_CMP CC_REG)
++	(compare:QUARK_CMP (match_operand:SF 0 "register_operand" "r")
++			   (match_operand:SF 1 "register_operand" "r")))
++   (clobber (match_scratch:SI 2 "=&r"))]
++  "TARGET_FPX_QUARK"
++  "dsp_fp_cmp\\t%2,%0,%1\\n\\trsub.f\\t0,%2,7\\n\\tcmp.nc\\t%2,1\\n\\tcmp.hi\\t%2,3"
++  [(set_attr "length" "16")
++   (set_attr "cond" "set")
++   (set_attr "predicable" "no")
++   (set_attr "cond" "nocond")])
++
++(define_insn "*cmpsf_quark_ord"
++  [(set (reg:CC_FP_ORD CC_REG)
++	(compare:CC_FP_ORD (match_operand:SF 0 "register_operand" "r")
++			   (match_operand:SF 1 "register_operand" "r")))
++   (clobber (match_scratch:SI 2 "=&r"))]
++  "TARGET_FPX_QUARK"
++  "dsp_fp_cmp\\t%2,%0,%1\\n\\tadd.f\\t%2,%2,-8"
++  [(set_attr "length" "8")
++   (set_attr "cond" "set")
++   (set_attr "predicable" "no")
++   (set_attr "cond" "nocond")])
++
++(define_insn "*cmpsf_quark_uneq"
++  [(set (reg:CC_FP_UNEQ CC_REG)
++	(compare:CC_FP_UNEQ (match_operand:SF 0 "register_operand" "r")
++			    (match_operand:SF 1 "register_operand" "r")))
++   (clobber (match_scratch:SI 2 "=&r"))]
++  "TARGET_FPX_QUARK"
++  "dsp_fp_cmp\\t%2,%0,%1\\n\\ttst\\t%2,6"
++  [(set_attr "length" "8")
++   (set_attr "cond" "set")
++   (set_attr "predicable" "no")
++   (set_attr "cond" "nocond")])
++
++(define_insn "*cmpsf_quark_eq"
++  [(set (reg:CC_Z CC_REG)
++	(compare:CC_Z (match_operand:SF 0 "register_operand" "r")
++		      (match_operand:SF 1 "register_operand" "r")))
++   (clobber (match_scratch:SI 2 "=&r"))]
++  "TARGET_FPX_QUARK"
++  "dsp_fp_cmp\\t%2,%0,%1\\n\\ttst\\t%2,0x0E"
++  [(set_attr "length" "8")
++   (set_attr "cond" "set")
++   (set_attr "predicable" "no")
++   (set_attr "cond" "nocond")])
++
++(define_insn "*divsf3_quark"
++  [(set (match_operand:SF 0 "register_operand"        "=r")
++	(div:SF (match_operand:SF 1 "register_operand" "r")
++		(match_operand:SF 2 "register_operand" "r")))]
++  "TARGET_FPX_QUARK"
++  "dsp_fp_div\\t%0,%1,%2"
++  [(set_attr "length" "4")
++   (set_attr "predicable" "no")
++   (set_attr "cond" "nocond")])
++
++(define_insn "*sqrtsf2_quark"
++  [(set (match_operand:SF 0 "register_operand"          "=r")
++	(sqrt:SF (match_operand:SF 1 "register_operand" "r")))]
++  "TARGET_FPX_QUARK"
++  "dsp_fp_sqrt\\t%0,%1"
++  [(set_attr "length" "4")
++   (set_attr "predicable" "no")
++   (set_attr "cond" "nocond")])
++
++;; SF->SI (using rounding towards zero)
++(define_insn "*fix_truncsfsi2_quark"
++  [(set (match_operand:SI 0 "register_operand"                "=r")
++	(fix:SI (fix:SF (match_operand:SF 1 "register_operand" "r"))))]
++  "TARGET_FPX_QUARK"
++  "dsp_fp_flt2i\\t%0,%1"
++  [(set_attr "length" "4")
++   (set_attr "predicable" "no")
++   (set_attr "cond" "nocond")])
++
++;; SI->SF
++(define_insn "*floatsisf2_quark"
++  [(set (match_operand:SF 0 "register_operand"          "=r")
++	(float:SF (match_operand:SI 1 "register_operand" "r")))]
++  "TARGET_FPX_QUARK"
++  "dsp_fp_i2flt\\t%0,%1"
++  [(set_attr "length" "4")
++   (set_attr "predicable" "no")
++   (set_attr "cond" "nocond")])
++
+diff --git a/gcc/config/arc/t-multilib b/gcc/config/arc/t-multilib
+index 1407bdf0d82c..0f1c398d61f8 100644
+--- a/gcc/config/arc/t-multilib
++++ b/gcc/config/arc/t-multilib
+@@ -21,15 +21,16 @@
+ # along with GCC; see the file COPYING3.  If not see
+ # <http://www.gnu.org/licenses/>.
+ 
+-MULTILIB_OPTIONS = mcpu=em/mcpu=arcem/mcpu=em4/mcpu=em4_dmips/mcpu=em4_fpus/mcpu=em4_fpuda/mcpu=hs/mcpu=archs/mcpu=hs34/mcpu=hs38/mcpu=hs38_linux/mcpu=arc600/mcpu=arc600_norm/mcpu=arc600_mul64/mcpu=arc600_mul32x16/mcpu=arc601/mcpu=arc601_norm/mcpu=arc601_mul64/mcpu=arc601_mul32x16/mcpu=arc700/mcpu=nps400
++MULTILIB_OPTIONS = mcpu=em/mcpu=arcem/mcpu=em4/mcpu=em4_dmips/mcpu=em4_fpus/mcpu=em4_fpuda/mcpu=quarkse_em/mcpu=hs/mcpu=archs/mcpu=hs34/mcpu=hs38/mcpu=hs38_linux/mcpu=arc600/mcpu=arc600_norm/mcpu=arc600_mul64/mcpu=arc600_mul32x16/mcpu=arc601/mcpu=arc601_norm/mcpu=arc601_mul64/mcpu=arc601_mul32x16/mcpu=arc700/mcpu=nps400
+ 
+-MULTILIB_DIRNAMES = em arcem em4 em4_dmips em4_fpus em4_fpuda hs archs hs34 hs38 hs38_linux arc600 arc600_norm arc600_mul64 arc600_mul32x16 arc601 arc601_norm arc601_mul64 arc601_mul32x16 arc700 nps400
++MULTILIB_DIRNAMES = em arcem em4 em4_dmips em4_fpus em4_fpuda quarkse_em hs archs hs34 hs38 hs38_linux arc600 arc600_norm arc600_mul64 arc600_mul32x16 arc601 arc601_norm arc601_mul64 arc601_mul32x16 arc700 nps400
+ 
+ MULTILIB_REUSE =mcpu.arcem=mcpu.em/mmpy-option.2/mcode-density/mbarrel-shifter
+ MULTILIB_REUSE +=mcpu.em4=mcpu.em/mcode-density
+ MULTILIB_REUSE +=mcpu.em4_dmips=mcpu.em/mmpy-option.2/mcode-density/mdiv-rem/mnorm/mnorm/mbarrel-shifter
+ MULTILIB_REUSE +=mcpu.em4_fpus=mcpu.em/mmpy-option.2/mcode-density/mdiv-rem/mnorm/mnorm/mbarrel-shifter/mfpu.fpus
+ MULTILIB_REUSE +=mcpu.em4_fpuda=mcpu.em/mmpy-option.2/mcode-density/mdiv-rem/mnorm/mnorm/mbarrel-shifter/mfpu.fpuda
++MULTILIB_REUSE +=mcpu.quarkse_em=mcpu.em/mmpy-option.3/mcode-density/mdiv-rem/mnorm/mnorm/mbarrel-shifter/quark/spfp/dpfp
+ MULTILIB_REUSE +=mcpu.archs=mcpu.hs/mmpy-option.2/mdiv-rem/mll64
+ MULTILIB_REUSE +=mcpu.hs34=mcpu.hs/mmpy-option.2
+ MULTILIB_REUSE +=mcpu.hs38=mcpu.hs/mmpy-option.9/mdiv-rem/mll64
+-- 
+2.7.4
+
diff --git a/toolchain/gcc/patches/6.3.0/0026-ARC-libgcc-Add-support-for-QuarkSE-processor.patch b/toolchain/gcc/patches/6.3.0/0026-ARC-libgcc-Add-support-for-QuarkSE-processor.patch
new file mode 100644
index 0000000..139bc84
--- /dev/null
+++ b/toolchain/gcc/patches/6.3.0/0026-ARC-libgcc-Add-support-for-QuarkSE-processor.patch
@@ -0,0 +1,441 @@
+From 17c52f2269de4d875c04f6bc372387b730fe7aca Mon Sep 17 00:00:00 2001
+From: Claudiu Zissulescu <claziss at synopsys.com>
+Date: Thu, 26 May 2016 11:08:52 +0200
+Subject: [PATCH 26/89] [ARC] [libgcc] Add support for QuarkSE processor.
+
+libgcc/
+2016-05-26  Claudiu Zissulescu  <claziss at synopsys.com>
+
+	* config/arc/dp-hack.h (ARC_OPTFPE): Define.
+	(__ARC_NORM__): Use instead ARC_OPTFPE.
+	* config/arc/fp-hack.h: Likewise.
+	* config/arc/lib1funcs.S (ARC_OPTFPE): Define.
+	(__ARC_MPY__): Use it insetead of __ARC700__ and __HS__.
+---
+ libgcc/config/arc/dp-hack.h   |  12 +++--
+ libgcc/config/arc/fp-hack.h   |   8 +--
+ libgcc/config/arc/lib1funcs.S | 120 ++++++++++++++++++++++--------------------
+ 3 files changed, 74 insertions(+), 66 deletions(-)
+
+diff --git a/libgcc/config/arc/dp-hack.h b/libgcc/config/arc/dp-hack.h
+index 3c727b122c0c..1f7f213288a2 100644
+--- a/libgcc/config/arc/dp-hack.h
++++ b/libgcc/config/arc/dp-hack.h
+@@ -30,21 +30,23 @@ see the files COPYING3 and COPYING.RUNTIME respectively.  If not, see
+ 
+ #define FINE_GRAINED_LIBRARIES
+ #define ARC_DP_DEBUG 1
+-#if !defined (__ARC_NORM__) || ARC_DP_DEBUG
++#define ARC_OPTFPE (defined (__ARC700__) || defined (__ARC_FPX_QUARK__))
++
++#if !ARC_OPTFPE || ARC_DP_DEBUG
+ #define L_pack_df
+ #define L_unpack_df
+ #define L_make_df
+ #define L_thenan_df
+ #define L_sf_to_df
+ #endif
+-#ifndef __ARC_NORM__
++#if !ARC_OPTFPE
+ #define L_addsub_df
+ #elif ARC_DP_DEBUG
+ #define L_addsub_df
+ #define __adddf3 __adddf3_c
+ #define __subdf3 __subdf3_c
+ #endif
+-#ifndef __ARC_NORM__
++#if !ARC_OPTFPE
+ #define L_mul_df
+ #define L_div_df
+ #elif (!defined (__ARC700__) && !defined (__ARC_MUL64__) \
+@@ -59,7 +61,7 @@ see the files COPYING3 and COPYING.RUNTIME respectively.  If not, see
+ #define L_div_df
+ #define __divdf3 __divdf3_c
+ #endif
+-#ifndef __ARC_NORM__
++#if !ARC_OPTFPE
+ #define L_df_to_sf
+ #define L_si_to_df
+ #define L_df_to_si
+@@ -77,7 +79,7 @@ see the files COPYING3 and COPYING.RUNTIME respectively.  If not, see
+ #define L_usi_to_df
+ #define __floatunsidf __floatunsidf_c
+ #endif
+-#ifndef __ARC_NORM__
++#if !ARC_OPTFPE
+ #define L_fpcmp_parts_df
+ #define L_compare_df
+ #define L_eq_df
+diff --git a/libgcc/config/arc/fp-hack.h b/libgcc/config/arc/fp-hack.h
+index 30b547a38403..5144bb950960 100644
+--- a/libgcc/config/arc/fp-hack.h
++++ b/libgcc/config/arc/fp-hack.h
+@@ -30,13 +30,15 @@ see the files COPYING3 and COPYING.RUNTIME respectively.  If not, see
+ 
+ #define ARC_FP_DEBUG 1
+ #define FINE_GRAINED_LIBRARIES
+-#if !defined (__ARC_NORM__) || ARC_FP_DEBUG
++#define ARC_OPTFPE (defined (__ARC700__) || defined (__ARC_FPX_QUARK__))
++
++#if !ARC_OPTFPE || ARC_FP_DEBUG
+ #define L_pack_sf
+ #define L_unpack_sf
+ #define L_make_sf
+ #define L_thenan_sf
+ #endif
+-#ifndef __ARC_NORM__
++#if !ARC_OPTFPE
+ #define L_addsub_sf
+ #define L_mul_sf
+ #define L_div_sf
+@@ -61,7 +63,7 @@ see the files COPYING3 and COPYING.RUNTIME respectively.  If not, see
+ #define L_usi_to_sf
+ #define __floatunsisf __floatunsisf_c
+ #endif
+-#ifndef __ARC_NORM__
++#if !ARC_OPTFPE
+ #define L_fpcmp_parts_sf
+ #define L_compare_sf
+ #define L_eq_sf
+diff --git a/libgcc/config/arc/lib1funcs.S b/libgcc/config/arc/lib1funcs.S
+index 1c8961cfb9dd..9bb25e0a90ed 100644
+--- a/libgcc/config/arc/lib1funcs.S
++++ b/libgcc/config/arc/lib1funcs.S
+@@ -32,29 +32,29 @@ see the files COPYING3 and COPYING.RUNTIME respectively.  If not, see
+    This exception does not however invalidate any other reasons why
+    the executable file might be covered by the GNU General Public License.  */
+ 
+- 
++
+  /* ANSI concatenation macros.  */
+- 
++
+  #define CONCAT1(a, b) CONCAT2(a, b)
+  #define CONCAT2(a, b) a ## b
+- 
++
+  /* Use the right prefix for global labels.  */
+- 
++
+  #define SYM(x) CONCAT1 (__USER_LABEL_PREFIX__, x)
+- 
++
+ #ifndef WORKING_ASSEMBLER
+ #define abs_l abs
+ #define asl_l asl
+ #define mov_l mov
+ #endif
+- 	
++
+ #define FUNC(X)         .type SYM(X), at function
+ #define HIDDEN_FUNC(X)	FUNC(X)` .hidden X
+ #define ENDFUNC0(X)     .Lfe_##X: .size X,.Lfe_##X-X
+ #define ENDFUNC(X)      ENDFUNC0(X)
+ 
+-	
+-	
++
++
+ #ifdef  L_mulsi3
+ 	.section .text
+ 	.align 4
+@@ -64,10 +64,10 @@ SYM(__mulsi3):
+ 
+ /* This the simple version.
+ 
+-  while (a) 
++  while (a)
+     {
+       if (a & 1)
+-        r += b;
++	r += b;
+       a >>= 1;
+       b <<= 1;
+     }
+@@ -132,7 +132,7 @@ SYM(__mulsi3):
+ 	add2.cs r0,r0,r1
+ 	lsr.f r2,r2
+ 	add3.cs r0,r0,r1
+-	bne.d .Loop	
++	bne.d .Loop
+ 	add3 r1,r3,r1
+ 	j_s	[blink]
+ 	ENDFUNC(__mulsi3)
+@@ -143,17 +143,17 @@ SYM(__mulsi3):
+ .Lloop:
+ 	bbit0 r0,0, at .Ly
+ 	add_s r2,r2,r1		; r += b
+-.Ly:	
++.Ly:
+ 	lsr_s r0,r0		; a >>= 1
+-	asl_s r1,r1		; b <<= 1	
+-	brne_s r0,0, at .Lloop	
++	asl_s r1,r1		; b <<= 1
++	brne_s r0,0, at .Lloop
+ .Ldone:
+ 	j_s.d [blink]
+ 	mov_s r0,r2
+ 	ENDFUNC(__mulsi3)
+ /********************************************************/
+ #endif
+-	
++
+ #endif /* L_mulsi3 */
+ 
+ #ifdef  L_umulsidi3
+@@ -178,10 +178,10 @@ SYM(__umulsi3_highpart):
+ 
+ /* This the simple version.
+ 
+-  while (a) 
++  while (a)
+     {
+       if (a & 1)
+-        r += b;
++	r += b;
+       a >>= 1;
+       b <<= 1;
+     }
+@@ -455,18 +455,18 @@ SYM(__udivmodsi4):
+ 	mov_s r2,1		; bit = 1
+ 	mov_s r3,0		; res = 0
+ .Lloop1:
+-  	brhs r1,r0, at .Lloop2
++	brhs r1,r0, at .Lloop2
+ 	bbit1 r1,31, at .Lloop2
+ 	asl_s r1,r1		; den <<= 1
+ 	b.d @.Lloop1
+ 	asl_s r2,r2		; bit <<= 1
+ .Lloop2:
+-  	brlo r0,r1, at .Lshiftdown
++	brlo r0,r1, at .Lshiftdown
+ 	sub_s r0,r0,r1		; num -= den
+ 	or_s r3,r3,r2		; res |= bit
+ .Lshiftdown:
+ 	lsr_s r2,r2		; bit >>= 1
+-	lsr_s r1,r1		; den >>= 1	
++	lsr_s r1,r1		; den >>= 1
+ 	brne_s r2,0, at .Lloop2
+ .Ldivmodend:
+ 	mov_s r1,r0		; r1 = mod
+@@ -785,15 +785,15 @@ __muldiv:
+ 	neg	r4,r2
+ 	ld.as	r5,[pcl,r4]
+ 	abs_s	r12,r0
+-        bic.f	0,r2,r4
+-        mpyhu.ne r12,r12,r5
++	bic.f	0,r2,r4
++	mpyhu.ne r12,r12,r5
+ 	norm	r3,r2
+ 	xor.f	0,r0,r1
+-        ; write port allocation stall
+-        rsub	r3,r3,30
+-        lsr	r0,r12,r3
+-        j_s.d	[blink]
+-        neg.mi	r0,r0
++	; write port allocation stall
++	rsub	r3,r3,30
++	lsr	r0,r12,r3
++	j_s.d	[blink]
++	neg.mi	r0,r0
+ 
+ 	.balign	4
+ SYM(__divsi3):
+@@ -876,7 +876,7 @@ SYM(__divsi3):
+ #endif	/* ifndef __ARC700__ */
+ 	ENDFUNC(__divsi3)
+ 
+-	
++
+ #endif /* L_divsi3 */
+ 
+ #ifdef  L_umodsi3
+@@ -951,7 +951,7 @@ SYM(__modsi3):
+        .section .text
+        .align 4
+        .global SYM (__clzsi2)
+-SYM(__clzsi2):	
++SYM(__clzsi2):
+ #ifdef __ARC_NORM__
+ 	HIDDEN_FUNC(__clzsi2)
+ 	norm.f	r0,r0
+@@ -1002,7 +1002,7 @@ SYM(__clzsi2):
+ 
+ 
+ ;;; MILLICODE THUNK LIB ;***************
+-	
++
+ ;;; 	.macro push_regs from, to, offset
+ ;;; 		st_s "\from", [sp, \offset]
+ ;;; 		.if \to-\from
+@@ -1019,22 +1019,22 @@ SYM(__clzsi2):
+ ;;;;   		.set regno, \from+1
+ ;;;;   		.set shift, 32
+ ;;;;   		.set shift, shift - 1
+-;;;;   #		st_s %shift @3 lsl #shift 
++;;;;   #		st_s %shift @3 lsl #shift
+ ;;;;   		.if \to-\from
+ ;;;;   		sum "(\from+1)", \to, "(\three)"
+-;;;;   		.endif		
++;;;;   		.endif
+ ;;;;   	.endm
+-;;;;   	
++;;;;
+ ;;;;   	SUM 0,5, 9
+-;;;;   	
+-;	.altmacro		
++;;;;
++;	.altmacro
+ ;;  	.macro push_regs from=0, to=3, offset
+ ;;  		st_s r\from, [sp, \offset]
+ ;;  		.if \to-\from
+ ;;  			push_regs "\from+1 ",\to,"(\offset+4)"
+ ;;  		.endif
+ ;;  	.endm
+-;;  
++;;
+ ;;  	.macro expand_to_push from=13, to
+ ;;  ;		.section .text
+ ;;  ;		.align 4
+@@ -1042,11 +1042,11 @@ SYM(__clzsi2):
+ ;;  ;		.type foo,
+ ;;  	st_13_to_25:
+ ;;  ;		push_regs \from, \to, 0
+-;;  	push_regs 0,3		; 
++;;  	push_regs 0,3		;
+ ;;  	.endm
+-;;  
++;;
+ ;;  	expand_to_push 13,18
+-;;  
++;;
+ ;#endif
+ 
+ #ifdef L_millicodethunk_st
+@@ -1077,25 +1077,25 @@ SYM(__clzsi2):
+ 	.align 4
+ SYM(__st_r13_to_r25):
+ 	st r25, [sp,48]
+-SYM(__st_r13_to_r24):	
++SYM(__st_r13_to_r24):
+ 	st r24, [sp,44]
+-SYM(__st_r13_to_r23):	
++SYM(__st_r13_to_r23):
+ 	st r23, [sp,40]
+-SYM(__st_r13_to_r22):	
++SYM(__st_r13_to_r22):
+ 	st r22, [sp,36]
+-SYM(__st_r13_to_r21):	
++SYM(__st_r13_to_r21):
+ 	st r21, [sp,32]
+-SYM(__st_r13_to_r20):	
+-	st r20, [sp,28]		
+-SYM(__st_r13_to_r19):	
++SYM(__st_r13_to_r20):
++	st r20, [sp,28]
++SYM(__st_r13_to_r19):
+ 	st r19, [sp,24]
+-SYM(__st_r13_to_r18):	
++SYM(__st_r13_to_r18):
+ 	st r18, [sp,20]
+-SYM(__st_r13_to_r17):	
++SYM(__st_r13_to_r17):
+ 	st r17, [sp,16]
+-SYM(__st_r13_to_r16):	
++SYM(__st_r13_to_r16):
+ 	st r16, [sp,12]
+-SYM(__st_r13_to_r15):	
++SYM(__st_r13_to_r15):
+ #ifdef __ARC700__
+ 	st r15, [sp,8] ; minimum function size to avoid stall: 6 bytes.
+ #else
+@@ -1103,7 +1103,7 @@ SYM(__st_r13_to_r15):
+ #endif
+ 	st_s r14, [sp,4]
+ 	j_s.d [%blink]
+-	st_s r13, [sp,0]	
++	st_s r13, [sp,0]
+ 	ENDFUNC(__st_r13_to_r15)
+ 	ENDFUNC(__st_r13_to_r16)
+ 	ENDFUNC(__st_r13_to_r17)
+@@ -1121,7 +1121,7 @@ SYM(__st_r13_to_r15):
+ #ifdef L_millicodethunk_ld
+ 	.section .text
+ 	.align 4
+-;	================================== 
++;	==================================
+ ;	the loads
+ 
+ 	.global SYM(__ld_r13_to_r15)
+@@ -1157,7 +1157,7 @@ SYM(__ld_r13_to_r22):
+ SYM(__ld_r13_to_r21):
+ 	ld r21, [sp,32]
+ SYM(__ld_r13_to_r20):
+-	ld r20, [sp,28]		
++	ld r20, [sp,28]
+ SYM(__ld_r13_to_r19):
+ 	ld r19, [sp,24]
+ SYM(__ld_r13_to_r18):
+@@ -1226,7 +1226,7 @@ SYM(__ld_r13_to_r22_ret):
+ SYM(__ld_r13_to_r21_ret):
+ 	ld r21, [sp,32]
+ SYM(__ld_r13_to_r20_ret):
+-	ld r20, [sp,28]		
++	ld r20, [sp,28]
+ SYM(__ld_r13_to_r19_ret):
+ 	ld r19, [sp,24]
+ SYM(__ld_r13_to_r18_ret):
+@@ -1258,6 +1258,9 @@ SYM(__ld_r13_to_r14_ret):
+ 
+ #endif /* L_millicodethunk_ret */
+ 
++#define ARC_OPTFPE (defined (__ARC700__) || defined (__ARC_FPX_QUARK__))
++
++#if ARC_OPTFPE
+ #ifdef  L_adddf3
+ #ifdef __ARC_NORM__
+ #include "ieee-754/adddf3.S"
+@@ -1265,7 +1268,7 @@ SYM(__ld_r13_to_r14_ret):
+ #endif
+ 
+ #ifdef  L_muldf3
+-#if defined (__ARC700__) || defined (__HS__)
++#ifdef __ARC_MPY__
+ #include "ieee-754/muldf3.S"
+ #elif defined (__ARC_NORM__) && defined(__ARC_MUL64__)
+ #include "ieee-754/arc600-mul64/muldf3.S"
+@@ -1281,7 +1284,7 @@ SYM(__ld_r13_to_r14_ret):
+ #endif
+ 
+ #ifdef  L_mulsf3
+-#if defined (__ARC700__) || defined (__HS__)
++#ifdef  __ARC_MPY__
+ #include "ieee-754/mulsf3.S"
+ #elif defined (__ARC_NORM__) && defined(__ARC_MUL64__)
+ #include "ieee-754/arc600-mul64/mulsf3.S"
+@@ -1293,7 +1296,7 @@ SYM(__ld_r13_to_r14_ret):
+ #endif
+ 
+ #ifdef  L_divdf3
+-#if defined (__ARC700__) || defined (__HS__)
++#ifdef  __ARC_MPY__
+ #include "ieee-754/divdf3.S"
+ #elif defined (__ARC_NORM__) && defined(__ARC_MUL64__)
+ #include "ieee-754/arc600-mul64/divdf3.S"
+@@ -1303,7 +1306,7 @@ SYM(__ld_r13_to_r14_ret):
+ #endif
+ 
+ #ifdef  L_divsf3
+-#if defined (__ARC700__) || defined (__HS__)
++#ifdef  __ARC_MPY__
+ #include "ieee-754/divsf3-stdmul.S"
+ #elif defined (__ARC_NORM__) && defined(__ARC_MUL64__)
+ #include "ieee-754/arc600-mul64/divsf3.S"
+@@ -1421,3 +1424,4 @@ SYM(__ld_r13_to_r14_ret):
+ #include "ieee-754/ordsf2.S"
+ #endif
+ #endif
++#endif /* ARC_OPTFPE */
+-- 
+2.7.4
+
diff --git a/toolchain/gcc/patches/6.3.0/0027-ARC-libgcc-Fix-defines.patch b/toolchain/gcc/patches/6.3.0/0027-ARC-libgcc-Fix-defines.patch
new file mode 100644
index 0000000..b4a4902
--- /dev/null
+++ b/toolchain/gcc/patches/6.3.0/0027-ARC-libgcc-Fix-defines.patch
@@ -0,0 +1,198 @@
+From 098f1cb27b914e0e1522e100ff662fc99691da28 Mon Sep 17 00:00:00 2001
+From: Claudiu Zissulescu <claziss at synopsys.com>
+Date: Thu, 26 May 2016 12:51:46 +0200
+Subject: [PATCH 27/89] [ARC] [libgcc] Fix defines
+
+libgcc/
+2016-05-26  Claudiu Zissulescu  <claziss at synopsys.com>
+
+	* config/arc/lib1funcs.S (__mulsi3): Use feature defines instead
+	of checking for cpus.
+	(__umulsidi3, __umulsi3_highpart, __udivmodsi4, __divsi3)
+	(__modsi3, __clzsi2): Likewise.
+---
+ libgcc/config/arc/lib1funcs.S | 45 +++++++++++++++++++++++--------------------
+ 1 file changed, 24 insertions(+), 21 deletions(-)
+
+diff --git a/libgcc/config/arc/lib1funcs.S b/libgcc/config/arc/lib1funcs.S
+index 9bb25e0a90ed..422fd956457c 100644
+--- a/libgcc/config/arc/lib1funcs.S
++++ b/libgcc/config/arc/lib1funcs.S
+@@ -79,7 +79,7 @@ SYM(__mulsi3):
+ 	j_s.d [blink]
+ 	mov_s r0,mlo
+ 	ENDFUNC(__mulsi3)
+-#elif defined (__ARC700__) || defined (__HS__)
++#elif defined (__ARC_MPY__)
+ 	HIDDEN_FUNC(__mulsi3)
+ 	mpyu	r0,r0,r1
+ 	nop_s
+@@ -98,7 +98,7 @@ SYM(__mulsi3):
+ 	add_s	r1,r1,r1
+ .Lend:	j_s [blink]
+ 	ENDFUNC(__mulsi3)
+-#elif !defined (__OPTIMIZE_SIZE__) && !defined(__ARC601__)
++#elif !defined (__OPTIMIZE_SIZE__) && defined (__ARC_BARREL_SHIFTER__)
+ 	/* Up to 3.5 times faster than the simpler code below, but larger.  */
+ 	FUNC(__mulsi3)
+ 	ror.f	r2,r0,4
+@@ -170,7 +170,8 @@ SYM(__umulsidi3):
+    umulsi3_highpart implementation; the use of the latter label doesn't
+    actually benefit ARC601 platforms, but is useful when ARC601 code is linked
+    against other libraries.  */
+-#if defined (__ARC700__) || defined (__ARC_MUL64__) || defined (__ARC601__)
++#if defined (__ARC_MPY__) || defined (__ARC_MUL64__) \
++	|| !defined (__ARC_BARREL_SHIFTER__)
+ 	.global SYM(__umulsi3_highpart)
+ SYM(__umulsi3_highpart):
+ 	HIDDEN_FUNC(__umulsi3_highpart)
+@@ -188,18 +189,18 @@ SYM(__umulsi3_highpart):
+ */
+ #include "ieee-754/arc-ieee-754.h"
+ 
+-#ifdef __ARC700__
++#ifdef __ARC_MPY__
+ 	mov_s	r12,DBL0L
+ 	mpyu	DBL0L,r12,DBL0H
+ 	j_s.d	[blink]
+-	mpyhu	DBL0H,r12,DBL0H
++	MPYHU	DBL0H,r12,DBL0H
+ #elif defined (__ARC_MUL64__)
+ /* Likewise for __ARC_MUL64__ */
+ 	mulu64 r0,r1
+ 	mov_s DBL0L,mlo
+ 	j_s.d [blink]
+ 	mov_s DBL0H,mhi
+-#else /* !__ARC700__ && !__ARC_MUL64__ */
++#else /* !__ARC_MPY__ && !__ARC_MUL64__ */
+ /* Although it might look tempting to extend this to handle muldi3,
+    using mulsi3 twice with 2.25 cycles per 32 bit add is faster
+    than one loop with 3 or four cycles per 32 bit add.  */
+@@ -223,9 +224,10 @@ SYM(__umulsi3_highpart):
+ 	mov_s DBL0L,r3
+ 	j_s.d [blink]
+ 	mov DBL0H,r2
+-#endif /* !__ARC700__*/
++#endif /* !__ARC_MPY__*/
+ 	ENDFUNC(__umulsidi3)
+-#if defined (__ARC700__) || defined (__ARC_MUL64__) || defined (__ARC601__)
++#if defined (__ARC_MPY__) || defined (__ARC_MUL64__) \
++	|| !defined (__ARC_BARREL_SHIFTER__)
+ 	ENDFUNC(__umulsi3_highpart)
+ #endif
+ #endif /* L_umulsidi3 */
+@@ -235,7 +237,8 @@ SYM(__umulsi3_highpart):
+ /* For use without a barrel shifter, and for ARC700 / ARC_MUL64, the
+    mulsidi3 algorithms above look better, so for these, there is an
+    extra label up there.  */
+-#if !defined (__ARC700__) && !defined (__ARC_MUL64__) && !defined (__ARC601__)
++#if !defined (__ARC_MPY__) && !defined (__ARC_MUL64__) \
++	&& defined (__ARC_BARREL_SHIFTER__)
+ 	.global SYM(__umulsi3_highpart)
+ SYM(__umulsi3_highpart):
+ 	HIDDEN_FUNC(__umulsi3_highpart)
+@@ -251,7 +254,7 @@ SYM(__umulsi3_highpart):
+ /* Make the result register peephole-compatible with mulsidi3.  */
+ 	lsr DBL0H,r2,r3
+ 	ENDFUNC(__umulsi3_highpart)
+-#endif /* !__ARC700__  && !__ARC601__ */
++#endif /* !__ARC_MPY__  && __ARC_BARREL_SHIFTER__ */
+ #endif /* L_umulsi3_highpart */
+ 
+ #ifdef L_divmod_tools
+@@ -295,7 +298,7 @@ udivmodsi4(int modwanted, unsigned long num, unsigned long den)
+ 	FUNC(__udivmodsi4)
+ SYM(__udivmodsi4):
+ 
+-#if defined (__ARC700__)
++#if defined (__ARC_EA__)
+ /* Normalize divisor and divident, and then use the appropriate number of
+    divaw (the number of result bits, or one more) to produce the result.
+    There are some special conditions that need to be tested:
+@@ -368,7 +371,7 @@ SYM(__udivmodsi4):
+ 	j_s.d	[blink]
+ 	mov.c	r0,0
+ #elif !defined (__OPTIMIZE_SIZE__)
+-#ifdef __ARC_NORM__
++#if defined (__ARC_NORM__) && defined (__ARC_BARREL_SHIFTER__)
+ 	lsr_s r2,r0
+ 	brhs.d r1,r2,.Lret0_3
+ 	norm r2,r2
+@@ -393,17 +396,17 @@ SYM(__udivmodsi4):
+ 	lsr_s r1,r1
+ 	cmp_s r0,r1
+ 	xor.f r2,lp_count,31
+-#if !defined (__EM__)
++#if !defined (__ARCEM__) && !defined (__ARCHS__)
+ 	mov_s lp_count,r2
+ #else
+ 	mov lp_count,r2
+ 	nop_s
+-#endif /* !__EM__ */
++#endif /* !__ARCEM__ && !__ARCHS__ */
+ #endif /* !__ARC_NORM__ */
+ 	sub.cc r0,r0,r1
+ 	mov_s r3,3
+ 	sbc r3,r3,0
+-#ifndef __ARC601__
++#if defined (__ARC_BARREL_SHIFTER__)
+ 	asl_s r3,r3,r2
+ 	rsub r1,r1,1
+ 	lpne @.Lloop2_end
+@@ -503,7 +506,7 @@ SYM(__udivsi3):
+ 	.global SYM(__divsi3)
+ 	FUNC(__divsi3)
+ 
+-#ifndef __ARC700__
++#ifndef __ARC_EA__
+ SYM(__divsi3):
+ 	/* A5 / ARC60? */
+ 	mov r7,blink
+@@ -514,7 +517,7 @@ SYM(__divsi3):
+ 	tst r6,r6
+ 	j.d [r7]
+ 	 neg.mi r0,r0
+-#else 	/* !ifndef __ARC700__ */
++#else 	/* !ifndef __ARC_EA__ */
+ 	;; We can use the abs, norm, divaw and mpy instructions for ARC700
+ #define MULDIV
+ #ifdef MULDIV
+@@ -907,7 +910,7 @@ SYM(__umodsi3):
+ 	.global SYM (__modsi3)
+ 	FUNC(__modsi3)
+ SYM(__modsi3):
+-#ifndef __ARC700__
++#ifndef __ARC_EA__
+ 	/* A5 / ARC60? */
+ 	mov_s r12,blink
+ 	mov_s r6,r0
+@@ -918,7 +921,7 @@ SYM(__modsi3):
+ 	neg_s r0,r1
+ 	j_s.d [r12]
+ 	 mov.pl r0,r1
+-#else /* __ARC700__ */
++#else /* __ARC_EA__ */
+ 	abs_s	r2,r1
+ 	norm.f	r4,r0
+ 	neg	r5,r2
+@@ -942,7 +945,7 @@ SYM(__modsi3):
+ 	cmp_s	r12,r2
+ 	j_s.d	[blink]
+ 	sub.hs	r0,r0,r5
+-#endif /* __ARC700__ */
++#endif /* !__ARC_EA__ */
+ 	ENDFUNC(__modsi3)
+ 
+ #endif /* L_modsi3 */
+@@ -959,7 +962,7 @@ SYM(__clzsi2):
+ 	j_s.d	[blink]
+ 	add.pl	r0,r0,1
+ 	ENDFUNC(__clzsi2)
+-#elif defined (__ARC601__)
++#elif !defined (__ARC_BARREL_SHIFTER__)
+ 	FUNC(__clzsi2)
+ 	mov lp_count,10
+ 	mov_l r1,0
+-- 
+2.7.4
+
diff --git a/toolchain/gcc/patches/6.3.0/0028-ARC-tests-Update-target-specific-tests.patch b/toolchain/gcc/patches/6.3.0/0028-ARC-tests-Update-target-specific-tests.patch
new file mode 100644
index 0000000..21c7599
--- /dev/null
+++ b/toolchain/gcc/patches/6.3.0/0028-ARC-tests-Update-target-specific-tests.patch
@@ -0,0 +1,1103 @@
+From 854d96b7ed61fda05faeef383390f875c1736d8d Mon Sep 17 00:00:00 2001
+From: Claudiu Zissulescu <claziss at synopsys.com>
+Date: Thu, 26 May 2016 15:06:04 +0200
+Subject: [PATCH 28/89] [ARC] [tests] Update target specific tests.
+
+gcc/
+[ARC] [tests] Update tests.
+
+gcc/
+2016-06-27  Claudiu Zissulescu  <claziss at synopsys.com>
+
+	* testsuite/gcc.target/arc/abitest.S: New file.
+	* testsuite/gcc.target/arc/abitest.h: Likewise.
+	* testsuite/gcc.target/arc/va_args-1.c: Likewise.
+	* testsuite/gcc.target/arc/va_args-2.c: Likewise.
+	* testsuite/gcc.target/arc/va_args-3.c: Likewise.
+	* testsuite/gcc.target/arc/mcrc.c: Deleted.
+	* testsuite/gcc.target/arc/mdsp-packa.c: Likewise.
+	* testsuite/gcc.target/arc/mdvbf.c: Likewise.
+	* testsuite/gcc.target/arc/mmac-24.c: Likewise.
+	* testsuite/gcc.target/arc/mmac-d16.c: Likewise.
+	* testsuite/gcc.target/arc/mno-crc.c: Likewise.
+	* testsuite/gcc.target/arc/mno-dsp-packa.c: Likewise.
+	* testsuite/gcc.target/arc/mno-dvbf.c: Likewise.
+	* testsuite/gcc.target/arc/mno-mac-24.c: Likewise.
+	* testsuite/gcc.target/arc/mno-mac-d16.c: Likewise.
+	* testsuite/gcc.target/arc/mno-rtsc.c: Likewise.
+	* testsuite/gcc.target/arc/mno-xy.c: Likewise.
+	* testsuite/gcc.target/arc/mrtsc.c: Likewise.
+	* testsuite/gcc.target/arc/arc.exp (check_effective_target_arcem):
+	New function.
+	(check_effective_target_arc700): Likewise.
+	(check_effective_target_arc6xx): Likewise.
+	(check_effective_target_arcmpy): Likewise.
+	(check_effective_target_archs): Likewise.
+	(check_effective_target_clmcpu): Likewise.
+	(check_effective_target_barrelshifter): Likewise.
+	* testsuite/gcc.target/arc/barrel-shifter-1.c: Changed.
+	* testsuite/gcc.target/arc/builtin_simd.c: Test only for ARC700
+	cpus.
+	* testsuite/gcc.target/arc/cmem-1.c: Changed.
+	* testsuite/gcc.target/arc/cmem-2.c: Likewise.
+	* testsuite/gcc.target/arc/cmem-3.c: Likewise.
+	* testsuite/gcc.target/arc/cmem-4.c: Likewise.
+	* testsuite/gcc.target/arc/cmem-5.c: Likewise.
+	* testsuite/gcc.target/arc/cmem-6.c: Likewise.
+	* testsuite/gcc.target/arc/cmem-7.c: Likewise.
+	* testsuite/gcc.target/arc/interrupt-1.c: Test for RTIE as well.
+	* testsuite/gcc.target/arc/interrupt-2.c: Skip it for ARCv2 cores.
+	* testsuite/gcc.target/arc/interrupt-3.c: Match also ARCv2
+	warnings.
+	* testsuite/gcc.target/arc/jump-around-jump.c: Update options.
+	* testsuite/gcc.target/arc/mARC601.c: Changed.
+	* testsuite/gcc.target/arc/mcpu-arc600.c: Changed.
+	* testsuite/gcc.target/arc/mcpu-arc601.c: Changed.
+	* testsuite/gcc.target/arc/mcpu-arc700.c: Changed.
+	* testsuite/gcc.target/arc/mdpfp.c: Skip for ARCv2 cores.
+	* testsuite/gcc.target/arc/movb-1.c: Changed.
+	* testsuite/gcc.target/arc/movb-2.c: Likewise.
+	* testsuite/gcc.target/arc/movb-3.c: Likewise.
+	* testsuite/gcc.target/arc/movb-4.c: Likewise.
+	* testsuite/gcc.target/arc/movb-5.c: Likewise.
+	* testsuite/gcc.target/arc/movb_cl-1.c: Likewise.
+	* testsuite/gcc.target/arc/movb_cl-2.c: Likewise.
+	* testsuite/gcc.target/arc/movbi_cl-1.c: Likewise.
+	* testsuite/gcc.target/arc/movh_cl-1.c: Likewise.
+	* testsuite/gcc.target/arc/mspfp.c: Skip for ARC HS cores.
+	* testsuite/gcc.target/arc/mul64.c: Enable it only for ARC600.
+	* testsuite/gcc.target/arc/mulsi3_highpart-1.c: Scan for ARCv2
+	instructions.
+	* testsuite/gcc.target/arc/mulsi3_highpart-2.c: Skip it for ARCv1
+	cores.
+	* testsuite/gcc.target/arc/no-dpfp-lrsr.c: Skip it for ARC HS.
+	* testsuite/gcc.target/arc/trsub.c: Only for ARC EM cores.
+	* testsuite/gcc.target/arc/builtin_simdarc.c: Changed.
+	* testsuite/gcc.target/arc/extzv-1.c: Likewise.
+	* testsuite/gcc.target/arc/insv-1.c: Likewise.
+	* testsuite/gcc.target/arc/insv-2.c: Likewise.
+	* testsuite/gcc.target/arc/mA6.c: Likewise.
+	* testsuite/gcc.target/arc/mA7.c: Likewise.
+	* testsuite/gcc.target/arc/mARC600.c: Likewise.
+	* testsuite/gcc.target/arc/mARC700.c: Likewise.
+	* testsuite/gcc.target/arc/mcpu-arc600.c: Likewise.
+	* testsuite/gcc.target/arc/mcpu-arc700.c: Likewise.
+	* testsuite/gcc.target/arc/movl-1.c: Likewise.
+	* testsuite/gcc.target/arc/nps400-1.c: Likewise.
+	* testsuite/gcc.target/arc/trsub.c: Likewise.
+	* testsuite/gcc.target/arc/barrel-shifter-2.c: Check for barrel
+	shifter configuration.
+	* testsuite/gcc.target/arc/mlock.c: Skip for arc6xx
+	configurations.
+	* testsuite/gcc.target/arc/mswape.c: Likewise.
+---
+ gcc/testsuite/gcc.target/arc/abitest.S           | 31 ++++++++++
+ gcc/testsuite/gcc.target/arc/abitest.h           | 17 ++++++
+ gcc/testsuite/gcc.target/arc/arc.exp             | 74 +++++++++++++++++++++++-
+ gcc/testsuite/gcc.target/arc/barrel-shifter-1.c  |  2 +-
+ gcc/testsuite/gcc.target/arc/barrel-shifter-2.c  |  1 +
+ gcc/testsuite/gcc.target/arc/builtin_simd.c      |  1 +
+ gcc/testsuite/gcc.target/arc/builtin_simdarc.c   |  1 +
+ gcc/testsuite/gcc.target/arc/cmem-1.c            |  1 +
+ gcc/testsuite/gcc.target/arc/cmem-2.c            |  1 +
+ gcc/testsuite/gcc.target/arc/cmem-3.c            |  1 +
+ gcc/testsuite/gcc.target/arc/cmem-4.c            |  1 +
+ gcc/testsuite/gcc.target/arc/cmem-5.c            |  1 +
+ gcc/testsuite/gcc.target/arc/cmem-6.c            |  1 +
+ gcc/testsuite/gcc.target/arc/cmem-7.c            |  1 +
+ gcc/testsuite/gcc.target/arc/extzv-1.c           |  1 +
+ gcc/testsuite/gcc.target/arc/insv-1.c            |  1 +
+ gcc/testsuite/gcc.target/arc/insv-2.c            |  1 +
+ gcc/testsuite/gcc.target/arc/interrupt-1.c       |  7 ++-
+ gcc/testsuite/gcc.target/arc/interrupt-2.c       |  1 +
+ gcc/testsuite/gcc.target/arc/interrupt-3.c       |  2 +-
+ gcc/testsuite/gcc.target/arc/jump-around-jump.c  |  2 +-
+ gcc/testsuite/gcc.target/arc/mA6.c               |  1 +
+ gcc/testsuite/gcc.target/arc/mA7.c               |  1 +
+ gcc/testsuite/gcc.target/arc/mARC600.c           |  1 +
+ gcc/testsuite/gcc.target/arc/mARC601.c           |  3 +-
+ gcc/testsuite/gcc.target/arc/mARC700.c           |  1 +
+ gcc/testsuite/gcc.target/arc/mcpu-arc600.c       |  3 +-
+ gcc/testsuite/gcc.target/arc/mcpu-arc601.c       |  5 +-
+ gcc/testsuite/gcc.target/arc/mcpu-arc700.c       |  3 +-
+ gcc/testsuite/gcc.target/arc/mcrc.c              |  9 ---
+ gcc/testsuite/gcc.target/arc/mdpfp.c             |  1 +
+ gcc/testsuite/gcc.target/arc/mdsp-packa.c        |  9 ---
+ gcc/testsuite/gcc.target/arc/mdvbf.c             |  9 ---
+ gcc/testsuite/gcc.target/arc/mlock.c             |  1 +
+ gcc/testsuite/gcc.target/arc/mmac-24.c           |  9 ---
+ gcc/testsuite/gcc.target/arc/mmac-d16.c          |  9 ---
+ gcc/testsuite/gcc.target/arc/mno-crc.c           | 11 ----
+ gcc/testsuite/gcc.target/arc/mno-dsp-packa.c     | 11 ----
+ gcc/testsuite/gcc.target/arc/mno-dvbf.c          | 11 ----
+ gcc/testsuite/gcc.target/arc/mno-mac-24.c        | 11 ----
+ gcc/testsuite/gcc.target/arc/mno-mac-d16.c       | 11 ----
+ gcc/testsuite/gcc.target/arc/mno-rtsc.c          | 11 ----
+ gcc/testsuite/gcc.target/arc/mno-xy.c            | 10 ----
+ gcc/testsuite/gcc.target/arc/movb-1.c            |  1 +
+ gcc/testsuite/gcc.target/arc/movb-2.c            |  1 +
+ gcc/testsuite/gcc.target/arc/movb-3.c            |  1 +
+ gcc/testsuite/gcc.target/arc/movb-4.c            |  1 +
+ gcc/testsuite/gcc.target/arc/movb-5.c            |  1 +
+ gcc/testsuite/gcc.target/arc/movb_cl-1.c         |  1 +
+ gcc/testsuite/gcc.target/arc/movb_cl-2.c         |  1 +
+ gcc/testsuite/gcc.target/arc/movbi_cl-1.c        |  1 +
+ gcc/testsuite/gcc.target/arc/movh_cl-1.c         |  1 +
+ gcc/testsuite/gcc.target/arc/movl-1.c            |  1 +
+ gcc/testsuite/gcc.target/arc/mrtsc.c             |  9 ---
+ gcc/testsuite/gcc.target/arc/mspfp.c             |  1 +
+ gcc/testsuite/gcc.target/arc/mswape.c            |  1 +
+ gcc/testsuite/gcc.target/arc/mul64.c             |  4 +-
+ gcc/testsuite/gcc.target/arc/mulsi3_highpart-1.c |  5 +-
+ gcc/testsuite/gcc.target/arc/mulsi3_highpart-2.c |  4 +-
+ gcc/testsuite/gcc.target/arc/no-dpfp-lrsr.c      |  1 +
+ gcc/testsuite/gcc.target/arc/nps400-1.c          |  1 +
+ gcc/testsuite/gcc.target/arc/trsub.c             |  1 +
+ gcc/testsuite/gcc.target/arc/va_args-1.c         | 16 +++++
+ gcc/testsuite/gcc.target/arc/va_args-2.c         | 14 +++++
+ gcc/testsuite/gcc.target/arc/va_args-3.c         | 15 +++++
+ 65 files changed, 227 insertions(+), 145 deletions(-)
+ create mode 100644 gcc/testsuite/gcc.target/arc/abitest.S
+ create mode 100644 gcc/testsuite/gcc.target/arc/abitest.h
+ delete mode 100644 gcc/testsuite/gcc.target/arc/mcrc.c
+ delete mode 100644 gcc/testsuite/gcc.target/arc/mdsp-packa.c
+ delete mode 100644 gcc/testsuite/gcc.target/arc/mdvbf.c
+ delete mode 100644 gcc/testsuite/gcc.target/arc/mmac-24.c
+ delete mode 100644 gcc/testsuite/gcc.target/arc/mmac-d16.c
+ delete mode 100644 gcc/testsuite/gcc.target/arc/mno-crc.c
+ delete mode 100644 gcc/testsuite/gcc.target/arc/mno-dsp-packa.c
+ delete mode 100644 gcc/testsuite/gcc.target/arc/mno-dvbf.c
+ delete mode 100644 gcc/testsuite/gcc.target/arc/mno-mac-24.c
+ delete mode 100644 gcc/testsuite/gcc.target/arc/mno-mac-d16.c
+ delete mode 100644 gcc/testsuite/gcc.target/arc/mno-rtsc.c
+ delete mode 100644 gcc/testsuite/gcc.target/arc/mno-xy.c
+ delete mode 100644 gcc/testsuite/gcc.target/arc/mrtsc.c
+ create mode 100644 gcc/testsuite/gcc.target/arc/va_args-1.c
+ create mode 100644 gcc/testsuite/gcc.target/arc/va_args-2.c
+ create mode 100644 gcc/testsuite/gcc.target/arc/va_args-3.c
+
+diff --git a/gcc/testsuite/gcc.target/arc/abitest.S b/gcc/testsuite/gcc.target/arc/abitest.S
+new file mode 100644
+index 000000000000..7be935b10346
+--- /dev/null
++++ b/gcc/testsuite/gcc.target/arc/abitest.S
+@@ -0,0 +1,31 @@
++/* { dg-do assemble } */
++#ifndef ENTRY
++#define ENTRY(nm)               \
++        .text `                 \
++        .align 4 `              \
++        .globl nm `             \
++        .type nm, at function `    \
++nm:
++#endif
++
++#ifndef END
++#define END(name)       .size name,.-name
++#endif
++
++ENTRY(tsyscall)
++ENTRY(clone)
++	add	r0,r0,r1
++	add	r0,r0,r2
++	add	r0,r0,r3
++	add	r0,r0,r4
++	add	r0,r0,r5
++	j_s.d	[blink]
++	add	r0,r0,r6
++END(tsyscall)
++END(clone)
++
++ENTRY(abidi)
++	add.f r0,r1,1
++        j_s.d [blink]
++        adc r1,r2,0
++END(abidi)
+diff --git a/gcc/testsuite/gcc.target/arc/abitest.h b/gcc/testsuite/gcc.target/arc/abitest.h
+new file mode 100644
+index 000000000000..26de3e4f7e42
+--- /dev/null
++++ b/gcc/testsuite/gcc.target/arc/abitest.h
+@@ -0,0 +1,17 @@
++#ifndef _DG_ABITEST_H
++#define _DG_ABITEST_H 1
++
++#ifdef  __ASSEMBLER__
++
++#define ENTRY(nm)               \
++        .text `                 \
++        .align 4 `              \
++        .globl nm `             \
++        .type nm, at function `    \
++nm:
++
++#define END(name)       .size name,.-name
++
++#endif /* __ASSEMBLER __*/
++
++#endif /*_DG_ABITEST_H*/
+diff --git a/gcc/testsuite/gcc.target/arc/arc.exp b/gcc/testsuite/gcc.target/arc/arc.exp
+index fae2ece7f6f3..62583cd0321e 100644
+--- a/gcc/testsuite/gcc.target/arc/arc.exp
++++ b/gcc/testsuite/gcc.target/arc/arc.exp
+@@ -4,12 +4,12 @@
+ # it under the terms of the GNU General Public License as published by
+ # the Free Software Foundation; either version 3 of the License, or
+ # (at your option) any later version.
+-# 
++#
+ # This program is distributed in the hope that it will be useful,
+ # but WITHOUT ANY WARRANTY; without even the implied warranty of
+ # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ # GNU General Public License for more details.
+-# 
++#
+ # You should have received a copy of the GNU General Public License
+ # along with GCC; see the file COPYING3.  If not see
+ # <http://www.gnu.org/licenses/>.
+@@ -24,6 +24,76 @@ if ![istarget arc*-*-*] then {
+ # Load support procs.
+ load_lib gcc-dg.exp
+ 
++# Return 1 if this is a compiler supporting ARCv2 EM as default processor
++proc check_effective_target_arcem { } {
++    return [check_no_compiler_messages arcem assembly {
++	#if !defined(__ARCEM__)
++	#error No ARC EM
++	#endif
++    }]
++}
++
++# Return 1 if we compile for ARC700
++proc check_effective_target_arc700 { } {
++    return [check_no_compiler_messages arc700 assembly {
++	#if !defined(__ARC700__)
++	#error No ARC 700
++	#endif
++    }]
++}
++
++# Return 1 if we compile for ARC6xx
++proc check_effective_target_arc6xx { } {
++    return [check_no_compiler_messages arc6xx assembly {
++	#if !defined(__ARC600__) && !defined(__ARC601__)
++	#error No ARC 6xx
++	#endif
++    }]
++}
++
++# Return 1 if we have mpy
++proc check_effective_target_arcmpy { } {
++    return [check_no_compiler_messages arcmpy assembly {
++	#if !defined(__ARC_MPY__)
++	#error No MPY
++	#endif
++    }]
++}
++
++# Return 1 if this is a compiler supporting ARC HS as default processor
++proc check_effective_target_archs { } {
++    return [check_no_compiler_messages archs assembly {
++	#if !defined(__ARCHS__)
++	#error No ARC HS
++	#endif
++    }]
++}
++
++proc check_cl { flags } {
++    return [check_no_compiler_messages check_$flags assembly {
++	#if !defined(__arc__)
++	#error Extra mcpu options
++	#endif
++    } "$flags"]
++}
++
++# Return 1 if there are no extra mcpu options given via command line
++proc check_effective_target_clmcpu { } {
++    if { [check_cl "-mcpu=arc700"]
++	 && [check_cl "-mcpu=arcem" ] } {
++	return 1
++    }
++    return 0
++}
++
++proc check_effective_target_barrelshifter { } {
++    return [check_no_compiler_messages barrelshifter assembly {
++	#if !defined(__ARC_BARREL_SHIFTER__)
++	#error No barrel shifter for this confi
++	#endif
++    }]
++}
++
+ # If a testcase doesn't have special options, use these.
+ global DEFAULT_CFLAGS
+ if ![info exists DEFAULT_CFLAGS] then {
+diff --git a/gcc/testsuite/gcc.target/arc/barrel-shifter-1.c b/gcc/testsuite/gcc.target/arc/barrel-shifter-1.c
+index a0eb6d70c39e..5cfb282f6ac7 100644
+--- a/gcc/testsuite/gcc.target/arc/barrel-shifter-1.c
++++ b/gcc/testsuite/gcc.target/arc/barrel-shifter-1.c
+@@ -1,5 +1,5 @@
+ /* { dg-do compile } */
+-/* { dg-options "-O2 -mcpu=ARC601 -mbarrel-shifter" } */
++/* { dg-options "-O2 -mbarrel-shifter" } */
+ int i;
+ 
+ int f (void)
+diff --git a/gcc/testsuite/gcc.target/arc/barrel-shifter-2.c b/gcc/testsuite/gcc.target/arc/barrel-shifter-2.c
+index 97998fbf1a38..8e0bb9a8a60b 100644
+--- a/gcc/testsuite/gcc.target/arc/barrel-shifter-2.c
++++ b/gcc/testsuite/gcc.target/arc/barrel-shifter-2.c
+@@ -1,4 +1,5 @@
+ /* { dg-do compile } */
++/* { dg-skip-if "" { ! { barrelshifter } } } */
+ int i;
+ 
+ int f (void)
+diff --git a/gcc/testsuite/gcc.target/arc/builtin_simd.c b/gcc/testsuite/gcc.target/arc/builtin_simd.c
+index fff27a479607..6b0252186c69 100644
+--- a/gcc/testsuite/gcc.target/arc/builtin_simd.c
++++ b/gcc/testsuite/gcc.target/arc/builtin_simd.c
+@@ -1,4 +1,5 @@
+ /* { dg-do compile } */
++/* { dg-skip-if "" { ! { clmcpu } } } */
+ /* { dg-options "-O2 -Werror-implicit-function-declaration -mARC700 -msimd" } */
+ 
+ #define STEST1(name, rettype, op1)		\
+diff --git a/gcc/testsuite/gcc.target/arc/builtin_simdarc.c b/gcc/testsuite/gcc.target/arc/builtin_simdarc.c
+index 68aae40ca58e..0cfe2ad767d4 100644
+--- a/gcc/testsuite/gcc.target/arc/builtin_simdarc.c
++++ b/gcc/testsuite/gcc.target/arc/builtin_simdarc.c
+@@ -1,4 +1,5 @@
+ /* { dg-do compile } */
++/* { dg-skip-if "" { ! { clmcpu } } } */
+ /* { dg-options "-mcpu=archs -O2 -Werror-implicit-function-declaration -mmpy-option=9" } */
+ 
+ #define STEST(name, rettype, op1type, op2type)	\
+diff --git a/gcc/testsuite/gcc.target/arc/cmem-1.c b/gcc/testsuite/gcc.target/arc/cmem-1.c
+index 7f36afbfa7d8..8ed5dcf2f019 100644
+--- a/gcc/testsuite/gcc.target/arc/cmem-1.c
++++ b/gcc/testsuite/gcc.target/arc/cmem-1.c
+@@ -1,4 +1,5 @@
+ /* { dg-do compile } */
++/* { dg-skip-if "" { ! { clmcpu } } } */
+ /* { dg-options "-mcpu=nps400 -mcmem" } */
+ 
+ #define CMEM_SECTION_ATTR __attribute__ ((section (".cmem")));
+diff --git a/gcc/testsuite/gcc.target/arc/cmem-2.c b/gcc/testsuite/gcc.target/arc/cmem-2.c
+index a3d7c130b5e8..39bfb2885c78 100644
+--- a/gcc/testsuite/gcc.target/arc/cmem-2.c
++++ b/gcc/testsuite/gcc.target/arc/cmem-2.c
+@@ -1,4 +1,5 @@
+ /* { dg-do compile } */
++/* { dg-skip-if "" { ! { clmcpu } } } */
+ /* { dg-options "-mcpu=nps400 -mcmem" } */
+ 
+ #define CMEM_SECTION_ATTR __attribute__ ((section (".cmem")));
+diff --git a/gcc/testsuite/gcc.target/arc/cmem-3.c b/gcc/testsuite/gcc.target/arc/cmem-3.c
+index dee73b5c5d30..109084f01fb3 100644
+--- a/gcc/testsuite/gcc.target/arc/cmem-3.c
++++ b/gcc/testsuite/gcc.target/arc/cmem-3.c
+@@ -1,4 +1,5 @@
+ /* { dg-do compile } */
++/* { dg-skip-if "" { ! { clmcpu } } } */
+ /* { dg-options "-mcpu=nps400 -mcmem" } */
+ 
+ #define CMEM_SECTION_ATTR __attribute__ ((section (".cmem_private")));
+diff --git a/gcc/testsuite/gcc.target/arc/cmem-4.c b/gcc/testsuite/gcc.target/arc/cmem-4.c
+index 1da6bce77c48..4ac8a22f2313 100644
+--- a/gcc/testsuite/gcc.target/arc/cmem-4.c
++++ b/gcc/testsuite/gcc.target/arc/cmem-4.c
+@@ -1,4 +1,5 @@
+ /* { dg-do compile } */
++/* { dg-skip-if "" { ! { clmcpu } } } */
+ /* { dg-options "-mcpu=nps400 -mcmem" } */
+ 
+ #define CMEM_SECTION_ATTR __attribute__ ((section (".cmem_private")));
+diff --git a/gcc/testsuite/gcc.target/arc/cmem-5.c b/gcc/testsuite/gcc.target/arc/cmem-5.c
+index ad6904f73605..451218b97651 100644
+--- a/gcc/testsuite/gcc.target/arc/cmem-5.c
++++ b/gcc/testsuite/gcc.target/arc/cmem-5.c
+@@ -1,4 +1,5 @@
+ /* { dg-do compile } */
++/* { dg-skip-if "" { ! { clmcpu } } } */
+ /* { dg-options "-mcpu=nps400 -mcmem" } */
+ 
+ #define CMEM_SECTION_ATTR __attribute__ ((section (".cmem_shared")));
+diff --git a/gcc/testsuite/gcc.target/arc/cmem-6.c b/gcc/testsuite/gcc.target/arc/cmem-6.c
+index 24bc39bfd07c..0ed06085514b 100644
+--- a/gcc/testsuite/gcc.target/arc/cmem-6.c
++++ b/gcc/testsuite/gcc.target/arc/cmem-6.c
+@@ -1,4 +1,5 @@
+ /* { dg-do compile } */
++/* { dg-skip-if "" { ! { clmcpu } } } */
+ /* { dg-options "-mcpu=nps400 -mcmem" } */
+ 
+ #define CMEM_SECTION_ATTR __attribute__ ((section (".cmem_shared")));
+diff --git a/gcc/testsuite/gcc.target/arc/cmem-7.c b/gcc/testsuite/gcc.target/arc/cmem-7.c
+index 72ee7bdffafb..026732711728 100644
+--- a/gcc/testsuite/gcc.target/arc/cmem-7.c
++++ b/gcc/testsuite/gcc.target/arc/cmem-7.c
+@@ -1,4 +1,5 @@
+ /* { dg-do compile } */
++/* { dg-skip-if "" { ! { clmcpu } } } */
+ /* { dg-options "-mcpu=nps400 -mcmem" } */
+ 
+ struct some_struct
+diff --git a/gcc/testsuite/gcc.target/arc/extzv-1.c b/gcc/testsuite/gcc.target/arc/extzv-1.c
+index 242f522f187e..1e5533a72bb7 100644
+--- a/gcc/testsuite/gcc.target/arc/extzv-1.c
++++ b/gcc/testsuite/gcc.target/arc/extzv-1.c
+@@ -1,4 +1,5 @@
+ /* { dg-do compile } */
++/* { dg-skip-if "" { ! { clmcpu } } } */
+ /* { dg-options "-mcpu=nps400 -O2 -mbitops" } */
+ 
+ struct foo { unsigned a: 3, b: 5, c: 24; };
+diff --git a/gcc/testsuite/gcc.target/arc/insv-1.c b/gcc/testsuite/gcc.target/arc/insv-1.c
+index 75d47e9b1b3f..29e4188a2e2b 100644
+--- a/gcc/testsuite/gcc.target/arc/insv-1.c
++++ b/gcc/testsuite/gcc.target/arc/insv-1.c
+@@ -1,4 +1,5 @@
+ /* { dg-do compile } */
++/* { dg-skip-if "" { ! { clmcpu } } } */
+ /* { dg-options "-mcpu=nps400 -O2 -mbitops" } */
+ 
+ /* ??? Irrespective of insn set, generated code for this is a mess.  */
+diff --git a/gcc/testsuite/gcc.target/arc/insv-2.c b/gcc/testsuite/gcc.target/arc/insv-2.c
+index 16525511698c..620acecc2e2f 100644
+--- a/gcc/testsuite/gcc.target/arc/insv-2.c
++++ b/gcc/testsuite/gcc.target/arc/insv-2.c
+@@ -1,4 +1,5 @@
+ /* { dg-do compile } */
++/* { dg-skip-if "" { ! { clmcpu } } } */
+ /* { dg-options "-mcpu=nps400 -O2 -mbitops" } */
+ 
+ struct foo { unsigned a: 3, b: 8, c: 21; } bar;
+diff --git a/gcc/testsuite/gcc.target/arc/interrupt-1.c b/gcc/testsuite/gcc.target/arc/interrupt-1.c
+index 70514572ea56..8a2002bf1c0f 100644
+--- a/gcc/testsuite/gcc.target/arc/interrupt-1.c
++++ b/gcc/testsuite/gcc.target/arc/interrupt-1.c
+@@ -1,5 +1,10 @@
++#if defined (__ARCHS__) || defined (__ARCEM__)
++void __attribute__ ((interrupt("ilink")))
++#else
+ void __attribute__ ((interrupt("ilink1")))
++#endif
+ handler1 (void)
+ {
+ }
+-/* { dg-final { scan-assembler-times "j.*\[ilink1\]" 1 } } */
++/* { dg-final { scan-assembler-times "j.*\[ilink1\]" 1 { target { arc700 || arc6xx } } } } */
++/* { dg-final { scan-assembler-times "rtie" 1 { target { arcem || archs } } } } */
+diff --git a/gcc/testsuite/gcc.target/arc/interrupt-2.c b/gcc/testsuite/gcc.target/arc/interrupt-2.c
+index ee8593b30391..285ebd57a220 100644
+--- a/gcc/testsuite/gcc.target/arc/interrupt-2.c
++++ b/gcc/testsuite/gcc.target/arc/interrupt-2.c
+@@ -1,3 +1,4 @@
++/* { dg-skip-if "ilink2 is not an ARCv2 register" { archs || arcem } } */
+ void __attribute__ ((interrupt("ilink2")))
+ handler1 (void)
+ {
+diff --git a/gcc/testsuite/gcc.target/arc/interrupt-3.c b/gcc/testsuite/gcc.target/arc/interrupt-3.c
+index fa598d67e6b1..b0cad88de95e 100644
+--- a/gcc/testsuite/gcc.target/arc/interrupt-3.c
++++ b/gcc/testsuite/gcc.target/arc/interrupt-3.c
+@@ -5,7 +5,7 @@ handler0 (void)
+ 
+ void __attribute__ ((interrupt("you load too")))
+ handler1 (void)
+-{ /* { dg-warning "is not \"ilink1\" or \"ilink2\"" } */
++{ /* { dg-warning "is not \"ilink" } */
+ }
+ 
+ void __attribute__ ((interrupt(42)))
+diff --git a/gcc/testsuite/gcc.target/arc/jump-around-jump.c b/gcc/testsuite/gcc.target/arc/jump-around-jump.c
+index 338c66752385..2fd3fb644c16 100644
+--- a/gcc/testsuite/gcc.target/arc/jump-around-jump.c
++++ b/gcc/testsuite/gcc.target/arc/jump-around-jump.c
+@@ -1,5 +1,5 @@
+ /* { dg-do compile } */
+-/* { dg-options "-Os -mlock -mswape -mrtsc -fno-reorder-blocks" } */
++/* { dg-options "-Os -mlock -mswape -fno-reorder-blocks" } */
+ 
+ /* This caused an ICE in arc_ifcvt when the 1->3 state change was not
+    implemented for TYPE_UNCOND_BRANCH in arc_ccfsm_post_advance.  */
+diff --git a/gcc/testsuite/gcc.target/arc/mA6.c b/gcc/testsuite/gcc.target/arc/mA6.c
+index 2e15a86f8a4d..c4eeb6feadcb 100644
+--- a/gcc/testsuite/gcc.target/arc/mA6.c
++++ b/gcc/testsuite/gcc.target/arc/mA6.c
+@@ -1,4 +1,5 @@
+ /* { dg-do compile } */
++/* { dg-skip-if "" { ! { clmcpu } } } */
+ /* { dg-options "-mA6" } */
+ 
+ /* { dg-final { scan-assembler ".cpu ARC600" } } */
+diff --git a/gcc/testsuite/gcc.target/arc/mA7.c b/gcc/testsuite/gcc.target/arc/mA7.c
+index c4430f43b416..a3c6f8204afb 100644
+--- a/gcc/testsuite/gcc.target/arc/mA7.c
++++ b/gcc/testsuite/gcc.target/arc/mA7.c
+@@ -1,4 +1,5 @@
+ /* { dg-do compile } */
++/* { dg-skip-if "" { ! { clmcpu } } } */
+ /* { dg-options "-mA7" } */
+ 
+ /* { dg-final { scan-assembler ".cpu ARC700" } } */
+diff --git a/gcc/testsuite/gcc.target/arc/mARC600.c b/gcc/testsuite/gcc.target/arc/mARC600.c
+index 20e086aa754f..6a80457b1945 100644
+--- a/gcc/testsuite/gcc.target/arc/mARC600.c
++++ b/gcc/testsuite/gcc.target/arc/mARC600.c
+@@ -1,4 +1,5 @@
+ /* { dg-do compile } */
++/* { dg-skip-if "" { ! { clmcpu } } } */
+ /* { dg-options "-mARC600" } */
+ 
+ /* { dg-final { scan-assembler ".cpu ARC600" } } */
+diff --git a/gcc/testsuite/gcc.target/arc/mARC601.c b/gcc/testsuite/gcc.target/arc/mARC601.c
+index 1d30da4cafb1..d2386613eb08 100644
+--- a/gcc/testsuite/gcc.target/arc/mARC601.c
++++ b/gcc/testsuite/gcc.target/arc/mARC601.c
+@@ -1,4 +1,5 @@
+ /* { dg-do compile } */
++/* { dg-skip-if "" { ! { clmcpu } } } */
+ /* { dg-options "-mARC601" } */
+ 
+-/* { dg-final { scan-assembler ".cpu ARC601" } } */
++/* { dg-final { scan-assembler ".cpu ARC60.*" } } */
+diff --git a/gcc/testsuite/gcc.target/arc/mARC700.c b/gcc/testsuite/gcc.target/arc/mARC700.c
+index 43e9baa3f301..d34583f46aa1 100644
+--- a/gcc/testsuite/gcc.target/arc/mARC700.c
++++ b/gcc/testsuite/gcc.target/arc/mARC700.c
+@@ -1,4 +1,5 @@
+ /* { dg-do compile } */
++/* { dg-skip-if "" { ! { clmcpu } } } */
+ /* { dg-options "-mARC700" } */
+ 
+ /* { dg-final { scan-assembler ".cpu ARC700" } } */
+diff --git a/gcc/testsuite/gcc.target/arc/mcpu-arc600.c b/gcc/testsuite/gcc.target/arc/mcpu-arc600.c
+index 4c915fda0e38..bd1dc9599a6d 100644
+--- a/gcc/testsuite/gcc.target/arc/mcpu-arc600.c
++++ b/gcc/testsuite/gcc.target/arc/mcpu-arc600.c
+@@ -1,4 +1,5 @@
+ /* { dg-do compile } */
+-/* { dg-options "-mcpu=ARC600" } */
++/* { dg-skip-if "" { ! { clmcpu } } } */
++/* { dg-options "-mcpu=arc600" } */
+ 
+ /* { dg-final { scan-assembler ".cpu ARC600" } } */
+diff --git a/gcc/testsuite/gcc.target/arc/mcpu-arc601.c b/gcc/testsuite/gcc.target/arc/mcpu-arc601.c
+index 7c93c9dc4acf..8ef046efb867 100644
+--- a/gcc/testsuite/gcc.target/arc/mcpu-arc601.c
++++ b/gcc/testsuite/gcc.target/arc/mcpu-arc601.c
+@@ -1,4 +1,5 @@
+ /* { dg-do compile } */
+-/* { dg-options "-mcpu=ARC601" } */
++/* { dg-skip-if "" { ! { clmcpu } } } */
++/* { dg-options "-mcpu=arc601" } */
+ 
+-/* { dg-final { scan-assembler ".cpu ARC601" } } */
++/* { dg-final { scan-assembler ".cpu ARC60.*" } } */
+diff --git a/gcc/testsuite/gcc.target/arc/mcpu-arc700.c b/gcc/testsuite/gcc.target/arc/mcpu-arc700.c
+index c805a5af76b1..25bb40029864 100644
+--- a/gcc/testsuite/gcc.target/arc/mcpu-arc700.c
++++ b/gcc/testsuite/gcc.target/arc/mcpu-arc700.c
+@@ -1,4 +1,5 @@
+ /* { dg-do compile } */
+-/* { dg-options "-mcpu=ARC700" } */
++/* { dg-skip-if "" { ! { clmcpu } } } */
++/* { dg-options "-mcpu=arc700" } */
+ 
+ /* { dg-final { scan-assembler ".cpu ARC700" } } */
+diff --git a/gcc/testsuite/gcc.target/arc/mcrc.c b/gcc/testsuite/gcc.target/arc/mcrc.c
+deleted file mode 100644
+index d3780bb00d6b..000000000000
+--- a/gcc/testsuite/gcc.target/arc/mcrc.c
++++ /dev/null
+@@ -1,9 +0,0 @@
+-/* { dg-do compile } */
+-/* { dg-options "-mcrc" } */
+-/* { dg-do assemble } */
+-
+-int f (int i)
+-{
+-  __asm__("crc %1, %1, %1" : "=r"(i) : "r"(i));
+-  return i;
+-}
+diff --git a/gcc/testsuite/gcc.target/arc/mdpfp.c b/gcc/testsuite/gcc.target/arc/mdpfp.c
+index 4bbc9057b856..aa6bdfa1c51f 100644
+--- a/gcc/testsuite/gcc.target/arc/mdpfp.c
++++ b/gcc/testsuite/gcc.target/arc/mdpfp.c
+@@ -1,4 +1,5 @@
+ /* { dg-do compile } */
++/* { dg-skip-if "FPX cannot execute on ARC HS" { archs } } */
+ /* { dg-options "-O2 -mdpfp" } */
+ 
+ double i;
+diff --git a/gcc/testsuite/gcc.target/arc/mdsp-packa.c b/gcc/testsuite/gcc.target/arc/mdsp-packa.c
+deleted file mode 100644
+index f013a6dd1ea6..000000000000
+--- a/gcc/testsuite/gcc.target/arc/mdsp-packa.c
++++ /dev/null
+@@ -1,9 +0,0 @@
+-/* { dg-do compile } */
+-/* { dg-options "-mdsp-packa" } */
+-/* { dg-do assemble } */
+-
+-int f (int i)
+-{
+-  __asm__("minidl %1, %1, %1" : "=r"(i) : "r"(i));
+-  return i;
+-}
+diff --git a/gcc/testsuite/gcc.target/arc/mdvbf.c b/gcc/testsuite/gcc.target/arc/mdvbf.c
+deleted file mode 100644
+index e2e545e8bb32..000000000000
+--- a/gcc/testsuite/gcc.target/arc/mdvbf.c
++++ /dev/null
+@@ -1,9 +0,0 @@
+-/* { dg-do compile } */
+-/* { dg-options "-mdvbf" } */
+-/* { dg-do assemble } */
+-
+-int f (int i)
+-{
+-  __asm__("vbfdw %1, %1" : "=r"(i) : "r"(i));
+-  return i;
+-}
+diff --git a/gcc/testsuite/gcc.target/arc/mlock.c b/gcc/testsuite/gcc.target/arc/mlock.c
+index 3a8b050c30ef..4b2d9e01f07f 100644
+--- a/gcc/testsuite/gcc.target/arc/mlock.c
++++ b/gcc/testsuite/gcc.target/arc/mlock.c
+@@ -1,6 +1,7 @@
+ /* { dg-do compile } */
+ /* { dg-options "-mlock" } */
+ /* { dg-do assemble } */
++/* { dg-skip-if "" { arc6xx } } */
+ 
+ int f (void *p)
+ {
+diff --git a/gcc/testsuite/gcc.target/arc/mmac-24.c b/gcc/testsuite/gcc.target/arc/mmac-24.c
+deleted file mode 100644
+index 30cb6981a03f..000000000000
+--- a/gcc/testsuite/gcc.target/arc/mmac-24.c
++++ /dev/null
+@@ -1,9 +0,0 @@
+-/* { dg-do compile } */
+-/* { dg-options "-mmac-24" } */
+-/* { dg-do assemble } */
+-
+-int f (int i)
+-{
+-  __asm__("mult %1, %1, %1" : "=r"(i) : "r"(i));
+-  return i;
+-}
+diff --git a/gcc/testsuite/gcc.target/arc/mmac-d16.c b/gcc/testsuite/gcc.target/arc/mmac-d16.c
+deleted file mode 100644
+index 0570011fd267..000000000000
+--- a/gcc/testsuite/gcc.target/arc/mmac-d16.c
++++ /dev/null
+@@ -1,9 +0,0 @@
+-/* { dg-do compile } */
+-/* { dg-options "-mmac-d16" } */
+-/* { dg-do assemble } */
+-
+-int f (int i)
+-{
+-  __asm__("muldw %1, %1, %1" : "=r"(i) : "r"(i));
+-  return i;
+-}
+diff --git a/gcc/testsuite/gcc.target/arc/mno-crc.c b/gcc/testsuite/gcc.target/arc/mno-crc.c
+deleted file mode 100644
+index 70ab9c117614..000000000000
+--- a/gcc/testsuite/gcc.target/arc/mno-crc.c
++++ /dev/null
+@@ -1,11 +0,0 @@
+-/* { dg-do compile } */
+-/* { dg-options "-mno-crc" } */
+-/* Would also like to assemble and check that we get the expected
+-   "Error: bad instruction" assembler messages, but at the moment our
+-   testharness can't do that.  */
+-
+-int f (int i)
+-{
+-  __asm__("crc %1, %1, %1" : "=r"(i) : "r"(i));
+-  return i;
+-}
+diff --git a/gcc/testsuite/gcc.target/arc/mno-dsp-packa.c b/gcc/testsuite/gcc.target/arc/mno-dsp-packa.c
+deleted file mode 100644
+index eb21522af063..000000000000
+--- a/gcc/testsuite/gcc.target/arc/mno-dsp-packa.c
++++ /dev/null
+@@ -1,11 +0,0 @@
+-/* { dg-do compile } */
+-/* { dg-options "-mno-dsp-packa" } */
+-/* Would also like to assemble and check that we get the expected
+-   "Error: bad instruction" assembler messages, but at the moment our
+-   testharness can't do that.  */
+-
+-int f (int i)
+-{
+-  __asm__("minidl %1, %1, %1" : "=r"(i) : "r"(i));
+-  return i;
+-}
+diff --git a/gcc/testsuite/gcc.target/arc/mno-dvbf.c b/gcc/testsuite/gcc.target/arc/mno-dvbf.c
+deleted file mode 100644
+index ea96d987c186..000000000000
+--- a/gcc/testsuite/gcc.target/arc/mno-dvbf.c
++++ /dev/null
+@@ -1,11 +0,0 @@
+-/* { dg-do compile } */
+-/* { dg-options "-mno-dvbf" } */
+-/* Would also like to assemble and check that we get the expected
+-   "Error: bad instruction" assembler messages, but at the moment our
+-   testharness can't do that.  */
+-
+-int f (int i)
+-{
+-  __asm__("vbfdw %1, %1" : "=r"(i) : "r"(i));
+-  return i;
+-}
+diff --git a/gcc/testsuite/gcc.target/arc/mno-mac-24.c b/gcc/testsuite/gcc.target/arc/mno-mac-24.c
+deleted file mode 100644
+index b4839579b125..000000000000
+--- a/gcc/testsuite/gcc.target/arc/mno-mac-24.c
++++ /dev/null
+@@ -1,11 +0,0 @@
+-/* { dg-do compile } */
+-/* { dg-options "-mno-mac-24" } */
+-/* Would also like to assemble and check that we get the expected
+-   "Error: bad instruction" assembler messages, but at the moment our
+-   testharness can't do that.  */
+-
+-int f (int i)
+-{
+-  __asm__("mult %1, %1, %1" : "=r"(i) : "r"(i));
+-  return i;
+-}
+diff --git a/gcc/testsuite/gcc.target/arc/mno-mac-d16.c b/gcc/testsuite/gcc.target/arc/mno-mac-d16.c
+deleted file mode 100644
+index 68a20f4f55ac..000000000000
+--- a/gcc/testsuite/gcc.target/arc/mno-mac-d16.c
++++ /dev/null
+@@ -1,11 +0,0 @@
+-/* { dg-do compile } */
+-/* { dg-options "-mno-mac-d16" } */
+-/* Would also like to assemble and check that we get the expected
+-   "Error: bad instruction" assembler messages, but at the moment our
+-   testharness can't do that.  */
+-
+-int f (int i)
+-{
+-  __asm__("muldw %1, %1, %1" : "=r"(i) : "r"(i));
+-  return i;
+-}
+diff --git a/gcc/testsuite/gcc.target/arc/mno-rtsc.c b/gcc/testsuite/gcc.target/arc/mno-rtsc.c
+deleted file mode 100644
+index d74a60e93514..000000000000
+--- a/gcc/testsuite/gcc.target/arc/mno-rtsc.c
++++ /dev/null
+@@ -1,11 +0,0 @@
+-/* { dg-do compile } */
+-/* { dg-options "-mno-rtsc" } */
+-/* Would also like to assemble and check that we get the expected
+-   "Error: bad instruction" assembler messages, but at the moment our
+-   testharness can't do that.  */
+-
+-int f (int i)
+-{
+-  __asm__("rtsc %1, %1" : "=r"(i) : "r"(i));
+-  return i;
+-}
+diff --git a/gcc/testsuite/gcc.target/arc/mno-xy.c b/gcc/testsuite/gcc.target/arc/mno-xy.c
+deleted file mode 100644
+index e378b3fc9b63..000000000000
+--- a/gcc/testsuite/gcc.target/arc/mno-xy.c
++++ /dev/null
+@@ -1,10 +0,0 @@
+-/* { dg-do compile } */
+-/* { dg-options "-mno-xy" } */
+-/* Would also like to assemble and check that we get the expected
+-   "Error: bad instruction" assembler messages, but at the moment our
+-   testharness can't do that.  */
+-
+-void f (int i)
+-{
+-  __asm__("add x0_u0, x0_u0, %0" : :  "r" (i));
+-}
+diff --git a/gcc/testsuite/gcc.target/arc/movb-1.c b/gcc/testsuite/gcc.target/arc/movb-1.c
+index 65d4ba4b6ab4..965fd66aa99c 100644
+--- a/gcc/testsuite/gcc.target/arc/movb-1.c
++++ b/gcc/testsuite/gcc.target/arc/movb-1.c
+@@ -1,4 +1,5 @@
+ /* { dg-do compile } */
++/* { dg-skip-if "" { ! { clmcpu } } } */
+ /* { dg-options "-mcpu=nps400 -O2 -mbitops" } */
+ 
+ struct { unsigned a: 5, b: 8, c: 19; } foo;
+diff --git a/gcc/testsuite/gcc.target/arc/movb-2.c b/gcc/testsuite/gcc.target/arc/movb-2.c
+index 1ba9976a566d..9bd6d4187fd3 100644
+--- a/gcc/testsuite/gcc.target/arc/movb-2.c
++++ b/gcc/testsuite/gcc.target/arc/movb-2.c
+@@ -1,4 +1,5 @@
+ /* { dg-do compile } */
++/* { dg-skip-if "" { ! { clmcpu } } } */
+ /* { dg-options "-mcpu=nps400 -O2 -mbitops" } */
+ 
+ struct { unsigned a: 23, b: 9; } foo;
+diff --git a/gcc/testsuite/gcc.target/arc/movb-3.c b/gcc/testsuite/gcc.target/arc/movb-3.c
+index 0895154abb67..34145d6cc6f2 100644
+--- a/gcc/testsuite/gcc.target/arc/movb-3.c
++++ b/gcc/testsuite/gcc.target/arc/movb-3.c
+@@ -1,4 +1,5 @@
+ /* { dg-do compile } */
++/* { dg-skip-if "" { ! { clmcpu } } } */
+ /* { dg-options "-mcpu=nps400 -O2 -mbitops" } */
+ 
+ struct { int a: 23, b: 9; } foo;
+diff --git a/gcc/testsuite/gcc.target/arc/movb-4.c b/gcc/testsuite/gcc.target/arc/movb-4.c
+index 89bf2c2b1232..83efad647d8d 100644
+--- a/gcc/testsuite/gcc.target/arc/movb-4.c
++++ b/gcc/testsuite/gcc.target/arc/movb-4.c
+@@ -1,4 +1,5 @@
+ /* { dg-do compile } */
++/* { dg-skip-if "" { ! { clmcpu } } } */
+ /* { dg-options "-mcpu=nps400 -O2 -mbitops" } */
+ 
+ struct { int a: 13, b: 19; } foo;
+diff --git a/gcc/testsuite/gcc.target/arc/movb-5.c b/gcc/testsuite/gcc.target/arc/movb-5.c
+index 9dbe8a1e09a8..0bcdd1c7874c 100644
+--- a/gcc/testsuite/gcc.target/arc/movb-5.c
++++ b/gcc/testsuite/gcc.target/arc/movb-5.c
+@@ -1,4 +1,5 @@
+ /* { dg-do compile } */
++/* { dg-skip-if "" { ! { clmcpu } } } */
+ /* { dg-options "-mcpu=nps400 -O2 -mbitops" } */
+ 
+ struct { int a: 23, b: 9; } foo;
+diff --git a/gcc/testsuite/gcc.target/arc/movb_cl-1.c b/gcc/testsuite/gcc.target/arc/movb_cl-1.c
+index 402250ce5302..977a0c2fbf02 100644
+--- a/gcc/testsuite/gcc.target/arc/movb_cl-1.c
++++ b/gcc/testsuite/gcc.target/arc/movb_cl-1.c
+@@ -1,4 +1,5 @@
+ /* { dg-do compile } */
++/* { dg-skip-if "" { ! { clmcpu } } } */
+ /* { dg-options "-mcpu=nps400 -O2 -mbitops" } */
+ 
+ int
+diff --git a/gcc/testsuite/gcc.target/arc/movb_cl-2.c b/gcc/testsuite/gcc.target/arc/movb_cl-2.c
+index d2e5a944a6ea..4a1484a3e4c7 100644
+--- a/gcc/testsuite/gcc.target/arc/movb_cl-2.c
++++ b/gcc/testsuite/gcc.target/arc/movb_cl-2.c
+@@ -1,4 +1,5 @@
+ /* { dg-do compile } */
++/* { dg-skip-if "" { ! { clmcpu } } } */
+ /* { dg-options "-mcpu=nps400 -O2 -mbitops" } */
+ 
+ extern void g (void);
+diff --git a/gcc/testsuite/gcc.target/arc/movbi_cl-1.c b/gcc/testsuite/gcc.target/arc/movbi_cl-1.c
+index 3c457dbe5287..a86d06f30b4e 100644
+--- a/gcc/testsuite/gcc.target/arc/movbi_cl-1.c
++++ b/gcc/testsuite/gcc.target/arc/movbi_cl-1.c
+@@ -1,4 +1,5 @@
+ /* { dg-do compile } */
++/* { dg-skip-if "" { ! { clmcpu } } } */
+ /* { dg-options "-mcpu=nps400 -O2 -mbitops" } */
+ 
+ int
+diff --git a/gcc/testsuite/gcc.target/arc/movh_cl-1.c b/gcc/testsuite/gcc.target/arc/movh_cl-1.c
+index 220cd9d72b94..13c0f3434433 100644
+--- a/gcc/testsuite/gcc.target/arc/movh_cl-1.c
++++ b/gcc/testsuite/gcc.target/arc/movh_cl-1.c
+@@ -1,4 +1,5 @@
+ /* { dg-do compile } */
++/* { dg-skip-if "" { ! { clmcpu } } } */
+ /* { dg-options "-mcpu=nps400 -O2 -mbitops" } */
+ 
+ struct thing
+diff --git a/gcc/testsuite/gcc.target/arc/movl-1.c b/gcc/testsuite/gcc.target/arc/movl-1.c
+index f1f0130a2b07..c44ca8d2ccde 100644
+--- a/gcc/testsuite/gcc.target/arc/movl-1.c
++++ b/gcc/testsuite/gcc.target/arc/movl-1.c
+@@ -1,4 +1,5 @@
+ /* { dg-do compile } */
++/* { dg-skip-if "" { ! { clmcpu } } } */
+ /* { dg-options "-mcpu=nps400 -O2 -mbitops" } */
+ 
+ int
+diff --git a/gcc/testsuite/gcc.target/arc/mrtsc.c b/gcc/testsuite/gcc.target/arc/mrtsc.c
+deleted file mode 100644
+index 31852a5e479b..000000000000
+--- a/gcc/testsuite/gcc.target/arc/mrtsc.c
++++ /dev/null
+@@ -1,9 +0,0 @@
+-/* { dg-do compile } */
+-/* { dg-options "-mrtsc" } */
+-/* { dg-do assemble } */
+-
+-int f (int i)
+-{
+-  __asm__("rtsc %1, %1" : "=r"(i) : "r"(i));
+-  return i;
+-}
+diff --git a/gcc/testsuite/gcc.target/arc/mspfp.c b/gcc/testsuite/gcc.target/arc/mspfp.c
+index 0e41ff89d351..19cb97828fbb 100644
+--- a/gcc/testsuite/gcc.target/arc/mspfp.c
++++ b/gcc/testsuite/gcc.target/arc/mspfp.c
+@@ -1,4 +1,5 @@
+ /* { dg-do compile } */
++/* { dg-skip-if "FPX is not an ARC HS extension" { archs } } */
+ /* { dg-options "-O2 -mspfp" } */
+ 
+ float i;
+diff --git a/gcc/testsuite/gcc.target/arc/mswape.c b/gcc/testsuite/gcc.target/arc/mswape.c
+index 692e6a2bb6ee..545968f114e2 100644
+--- a/gcc/testsuite/gcc.target/arc/mswape.c
++++ b/gcc/testsuite/gcc.target/arc/mswape.c
+@@ -1,6 +1,7 @@
+ /* { dg-do compile } */
+ /* { dg-options "-mswape" } */
+ /* { dg-do assemble } */
++/* { dg-skip-if "" { arc6xx } } */
+ 
+ int f (int i)
+ {
+diff --git a/gcc/testsuite/gcc.target/arc/mul64.c b/gcc/testsuite/gcc.target/arc/mul64.c
+index 3678b2799d54..fb8e7750c535 100644
+--- a/gcc/testsuite/gcc.target/arc/mul64.c
++++ b/gcc/testsuite/gcc.target/arc/mul64.c
+@@ -1,5 +1,7 @@
+ /* { dg-do compile } */
+-/* { dg-options "-O2 -mcpu=ARC600 -mmul64" } */
++/* { dg-skip-if "MUL64 is ARC600 extension" { ! { arc6xx } } } */
++/* { dg-options "-O2 -mmul64" } */
++
+ #include <stdint.h>
+ 
+ int64_t i;
+diff --git a/gcc/testsuite/gcc.target/arc/mulsi3_highpart-1.c b/gcc/testsuite/gcc.target/arc/mulsi3_highpart-1.c
+index 398ecfe948ee..57cb95b91fc1 100644
+--- a/gcc/testsuite/gcc.target/arc/mulsi3_highpart-1.c
++++ b/gcc/testsuite/gcc.target/arc/mulsi3_highpart-1.c
+@@ -1,5 +1,5 @@
+ /* { dg-do run } */
+-/* { dg-options "-O2 -mARC700 --save-temps" } */
++/* { dg-options "-save-temps -O2" } */
+ 
+ #include <stdlib.h>
+ 
+@@ -25,4 +25,5 @@ main (void)
+   return 0;
+ }
+ 
+-/* { dg-final { scan-assembler "mpyhu\[ \t\]" } } */
++/* { dg-final { scan-assembler "mpyhu\[ \t\]" { target { arc700 } } } } */
++/* { dg-final { scan-assembler "mpy.u\[ \t\]" { target { { ! { arc700 } } && arcmpy } } } } */
+diff --git a/gcc/testsuite/gcc.target/arc/mulsi3_highpart-2.c b/gcc/testsuite/gcc.target/arc/mulsi3_highpart-2.c
+index ccc74e7b1ada..287d96d4ee9a 100644
+--- a/gcc/testsuite/gcc.target/arc/mulsi3_highpart-2.c
++++ b/gcc/testsuite/gcc.target/arc/mulsi3_highpart-2.c
+@@ -1,5 +1,7 @@
+ /* { dg-do run } */
+-/* { dg-options "-O2 -mARC700 --save-temps -mno-mpy" } */
++/* { dg-skip-if "ARC700 always has mpy option on" { arc700 } } */
++/* { dg-skip-if "ARC600 doesn't have mpy instruction" { arc6xx } } */
++/* { dg-options "-O2 --save-temps -mmpy-option=0" } */
+ 
+ #include <stdlib.h>
+ 
+diff --git a/gcc/testsuite/gcc.target/arc/no-dpfp-lrsr.c b/gcc/testsuite/gcc.target/arc/no-dpfp-lrsr.c
+index e4e23e4a40f6..61f07b53aace 100644
+--- a/gcc/testsuite/gcc.target/arc/no-dpfp-lrsr.c
++++ b/gcc/testsuite/gcc.target/arc/no-dpfp-lrsr.c
+@@ -1,4 +1,5 @@
+ /* { dg-do compile } */
++/* { dg-skip-if "FPX cannot execute on ARC HS" { archs } } */
+ /* { dg-options "-O2 -mdpfp -mno-dpfp-lrsr" } */
+ 
+ double i;
+diff --git a/gcc/testsuite/gcc.target/arc/nps400-1.c b/gcc/testsuite/gcc.target/arc/nps400-1.c
+index f3d62718bb07..504aad734ccb 100644
+--- a/gcc/testsuite/gcc.target/arc/nps400-1.c
++++ b/gcc/testsuite/gcc.target/arc/nps400-1.c
+@@ -1,4 +1,5 @@
+ /* { dg-do compile } */
++/* { dg-skip-if "" { ! { clmcpu } } } */
+ /* { dg-options "-mcpu=nps400 -mq-class -mbitops -munaligned-access -mcmem -O2 -fno-strict-aliasing" } */
+ 
+ enum npsdp_mem_space_type {
+diff --git a/gcc/testsuite/gcc.target/arc/trsub.c b/gcc/testsuite/gcc.target/arc/trsub.c
+index 031935fdc8f5..8ea5711c6ee4 100644
+--- a/gcc/testsuite/gcc.target/arc/trsub.c
++++ b/gcc/testsuite/gcc.target/arc/trsub.c
+@@ -1,6 +1,7 @@
+ /* Tests if we generate rsub instructions when compiling using
+    floating point assist instructions.  */
+ /* { dg-do compile } */
++/* { dg-skip-if "" { ! { clmcpu } } } */
+ /* { dg-options "-mfpu=fpuda -mcpu=arcem" } */
+ 
+ double foo (double a)
+diff --git a/gcc/testsuite/gcc.target/arc/va_args-1.c b/gcc/testsuite/gcc.target/arc/va_args-1.c
+new file mode 100644
+index 000000000000..4a35d122ade4
+--- /dev/null
++++ b/gcc/testsuite/gcc.target/arc/va_args-1.c
+@@ -0,0 +1,16 @@
++/* { dg-do run } */
++/* { dg-options "-O2" } */
++/* { dg-additional-sources "abitest.S" } */
++
++extern long tsyscall (long int sysnum, ...);
++
++int main (void)
++{
++  long a;
++
++  a = tsyscall (1, 2, 3, 4, 5, 6, 7);
++
++  if (a != 28)
++    return 1;
++  return 0;
++}
+diff --git a/gcc/testsuite/gcc.target/arc/va_args-2.c b/gcc/testsuite/gcc.target/arc/va_args-2.c
+new file mode 100644
+index 000000000000..18f48b030b04
+--- /dev/null
++++ b/gcc/testsuite/gcc.target/arc/va_args-2.c
+@@ -0,0 +1,14 @@
++/* { dg-do run } */
++/* { dg-options "-O2" } */
++/* { dg-additional-sources "abitest.S" } */
++
++extern int clone(int (*fn)(void *), void *child_stack,
++		 int flags, void *arg, ...);
++
++int main (void)
++{
++  int a = clone ((void *) 1, (void *)2, 3, (void *) 4, 5, 6, 7);
++  if (a != 28)
++    return 1;
++  return 0;
++}
+diff --git a/gcc/testsuite/gcc.target/arc/va_args-3.c b/gcc/testsuite/gcc.target/arc/va_args-3.c
+new file mode 100644
+index 000000000000..45624c153c67
+--- /dev/null
++++ b/gcc/testsuite/gcc.target/arc/va_args-3.c
+@@ -0,0 +1,15 @@
++/* { dg-do run } */
++/* { dg-options "-O2" } */
++/* { dg-additional-sources "abitest.S" } */
++
++extern long long abidi (int a, ...);
++
++int main (void)
++{
++  long long a = 1;
++  a = abidi (10, a);
++
++  if (a != 2)
++    return 1;
++  return 0;
++}
+-- 
+2.7.4
+
diff --git a/toolchain/gcc/patches/6.3.0/0029-ARC-Various-fixes.patch b/toolchain/gcc/patches/6.3.0/0029-ARC-Various-fixes.patch
new file mode 100644
index 0000000..c0d8c5a
--- /dev/null
+++ b/toolchain/gcc/patches/6.3.0/0029-ARC-Various-fixes.patch
@@ -0,0 +1,84 @@
+From 955d2b920d3557f505179c11a61d10b7b9ff4f93 Mon Sep 17 00:00:00 2001
+From: Claudiu Zissulescu <claziss at synopsys.com>
+Date: Tue, 7 Jun 2016 11:01:48 +0200
+Subject: [PATCH 29/89] [ARC] Various fixes.
+
+The ifconversion was failing because a move involving the lp_count was
+not match by movsi_ne.  This patch updates the constraints such that
+movsi_ne will match.  The failing test is dg-torture.exp=pr68955.c for
+archs and without small data.
+
+gcc/
+2016-07-11  Claudiu Zissulescu  <claziss at synopsys.com>
+
+	* config/arc/arc.h (REG_CLASS_NAMES): Reorder.
+	* config/arc/arc.md (*add_n): Change.
+	(*sub_n): Likewise.
+	(movsi_ne): Update constraint to Rac.
+---
+ gcc/config/arc/arc.h  |  2 +-
+ gcc/config/arc/arc.md | 18 +++++++++---------
+ 2 files changed, 10 insertions(+), 10 deletions(-)
+
+diff --git a/gcc/config/arc/arc.h b/gcc/config/arc/arc.h
+index 795831d2c810..365062ede280 100644
+--- a/gcc/config/arc/arc.h
++++ b/gcc/config/arc/arc.h
+@@ -619,10 +619,10 @@ enum reg_class
+   "MPY_WRITABLE_CORE_REGS",   \
+   "WRITABLE_CORE_REGS",   \
+   "CHEAP_CORE_REGS",	  \
++  "ALL_CORE_REGS",	  \
+   "R0R3_CD_REGS", \
+   "R0R1_CD_REGS", \
+   "AC16_H_REGS",	    \
+-  "ALL_CORE_REGS",	  \
+   "ALL_REGS"          	  \
+ }
+ 
+diff --git a/gcc/config/arc/arc.md b/gcc/config/arc/arc.md
+index 87e6a172a9a5..375f2b7fa2bc 100644
+--- a/gcc/config/arc/arc.md
++++ b/gcc/config/arc/arc.md
+@@ -2901,10 +2901,10 @@
+    (set (match_dup 3) (match_dup 4))])
+ 
+ (define_insn "*add_n"
+-  [(set (match_operand:SI 0 "dest_reg_operand" "=Rcqq,Rcw,W,W,w,w")
+-	(plus:SI (mult:SI (match_operand:SI 1 "register_operand" "Rcqq,c,c,c,c,c")
+-			  (match_operand:SI 2 "_2_4_8_operand" ""))
+-		 (match_operand:SI 3 "nonmemory_operand" "0,0,c,?Cal,?c,??Cal")))]
++  [(set (match_operand:SI 0 "dest_reg_operand"                  "=Rcqq,Rcw,W,   W,w,w")
++	(plus:SI (mult:SI (match_operand:SI 1 "register_operand" "Rcqq,  c,c,   c,w,w")
++			  (match_operand:SI 2 "_2_4_8_operand"   ""))
++		 (match_operand:SI 3 "nonmemory_operand"            "0,  0,c,?Cal,c,Cal")))]
+   ""
+   "add%z2%? %0,%3,%1%&"
+   [(set_attr "type" "shift")
+@@ -2916,9 +2916,9 @@
+ ;; N.B. sub[123] has the operands of the MINUS in the opposite order from
+ ;; what synth_mult likes.
+ (define_insn "*sub_n"
+-  [(set (match_operand:SI 0 "dest_reg_operand" "=Rcw,w,w")
+-	(minus:SI (match_operand:SI 1 "nonmemory_operand" "0,c,?Cal")
+-		  (mult:SI (match_operand:SI 2 "register_operand" "c,c,c")
++  [(set (match_operand:SI 0 "dest_reg_operand"                 "=Rcw,w,w")
++	(minus:SI (match_operand:SI 1 "nonmemory_operand"         "0,c,?Cal")
++		  (mult:SI (match_operand:SI 2 "register_operand" "w,w,w")
+ 			   (match_operand:SI 3 "_2_4_8_operand" ""))))]
+   ""
+   "sub%z3%? %0,%1,%2"
+@@ -3574,8 +3574,8 @@
+ (define_insn "*movsi_ne"
+   [(cond_exec
+      (ne (match_operand:CC_Z 2 "cc_use_register"    "Rcc,  Rcc,  Rcc,Rcc,Rcc") (const_int 0))
+-     (set (match_operand:SI 0 "dest_reg_operand" "=Rcq#q,Rcq#q,Rcq#q,  w,w")
+-	  (match_operand:SI 1 "nonmemory_operand"   "C_0,    h, ?Cal, Lc,?Cal")))]
++     (set (match_operand:SI 0 "dest_reg_operand" "=Rcq#q,Rcq#q,Rcq#q,   w,w")
++	  (match_operand:SI 1 "nonmemory_operand"   "C_0,    h, ?Cal,LRac,?Cal")))]
+   ""
+   "@
+ 	* current_insn_predicate = 0; return \"sub%?.ne %0,%0,%0%&\";
+-- 
+2.7.4
+
diff --git a/toolchain/gcc/patches/6.3.0/0030-ARC-Add-simple-shift-rotate-ops.patch b/toolchain/gcc/patches/6.3.0/0030-ARC-Add-simple-shift-rotate-ops.patch
new file mode 100644
index 0000000..175ecf0
--- /dev/null
+++ b/toolchain/gcc/patches/6.3.0/0030-ARC-Add-simple-shift-rotate-ops.patch
@@ -0,0 +1,68 @@
+From c17c97bccaec0db96c468c575bbc769d1478a756 Mon Sep 17 00:00:00 2001
+From: Claudiu Zissulescu <claziss at synopsys.com>
+Date: Thu, 9 Jun 2016 13:26:21 +0200
+Subject: [PATCH 30/89] [ARC] Add simple shift/rotate ops.
+
+gcc/
+2016-06-09  Claudiu Zissulescu  <claziss at synopsys.com>
+
+	* config/arc/arc.md (*rotrsi3_cnt1): New pattern,
+	(*ashlsi2_cnt1, *lshrsi3_cnt1, *ashrsi3_cnt1): Likewise.
+---
+ gcc/config/arc/arc.md | 40 ++++++++++++++++++++++++++++++++++++++++
+ 1 file changed, 40 insertions(+)
+
+diff --git a/gcc/config/arc/arc.md b/gcc/config/arc/arc.md
+index 375f2b7fa2bc..64afb8bf7bf6 100644
+--- a/gcc/config/arc/arc.md
++++ b/gcc/config/arc/arc.md
+@@ -6219,6 +6219,46 @@
+ 		   (zero_extract:SI (match_dup 1) (match_dup 5) (match_dup 7)))])
+    (match_dup 1)])
+ 
++(define_insn "*rotrsi3_cnt1"
++  [(set (match_operand:SI 0 "dest_reg_operand"             "=w")
++	(rotatert:SI (match_operand:SI 1 "register_operand" "c")
++		     (const_int 1)))]
++  ""
++  "ror %0,%1%&"
++  [(set_attr "type" "shift")
++   (set_attr "predicable" "no")
++   (set_attr "length" "4")])
++
++(define_insn "*ashlsi2_cnt1"
++  [(set (match_operand:SI 0 "dest_reg_operand"           "=Rcqq,w")
++	(ashift:SI (match_operand:SI 1 "register_operand" "Rcqq,c")
++		   (const_int 1)))]
++  ""
++  "asl%? %0,%1%&"
++  [(set_attr "type" "shift")
++   (set_attr "iscompact" "maybe,false")
++   (set_attr "predicable" "no,no")])
++
++(define_insn "*lshrsi3_cnt1"
++  [(set (match_operand:SI 0 "dest_reg_operand"             "=Rcqq,w")
++	(lshiftrt:SI (match_operand:SI 1 "register_operand" "Rcqq,c")
++		     (const_int 1)))]
++  ""
++  "lsr%? %0,%1%&"
++  [(set_attr "type" "shift")
++   (set_attr "iscompact" "maybe,false")
++   (set_attr "predicable" "no,no")])
++
++(define_insn "*ashrsi3_cnt1"
++  [(set (match_operand:SI 0 "dest_reg_operand"             "=Rcqq,w")
++	(ashiftrt:SI (match_operand:SI 1 "register_operand" "Rcqq,c")
++		     (const_int 1)))]
++  ""
++  "asr%? %0,%1%&"
++  [(set_attr "type" "shift")
++   (set_attr "iscompact" "maybe,false")
++   (set_attr "predicable" "no,no")])
++
+ ;; include the arc-FPX instructions
+ (include "fpx.md")
+ 
+-- 
+2.7.4
+
diff --git a/toolchain/gcc/patches/6.3.0/0031-Fix-option-text.patch b/toolchain/gcc/patches/6.3.0/0031-Fix-option-text.patch
new file mode 100644
index 0000000..8f35b81
--- /dev/null
+++ b/toolchain/gcc/patches/6.3.0/0031-Fix-option-text.patch
@@ -0,0 +1,44 @@
+From e1ffdb7dee37fbb8c2b4cf42d639d2550086ca5c Mon Sep 17 00:00:00 2001
+From: claziss <claziss at 138bc75d-0d04-0410-961f-82ee72b054a4>
+Date: Thu, 16 Jun 2016 10:37:37 +0000
+Subject: [PATCH 31/89] Fix option text.
+
+gcc/
+2016-06-16  Claudiu Zissulescu  <claziss at synopsys.com>
+
+	* config/arc/arc.opt (mtp-regno): Update text.
+
+git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@237519 138bc75d-0d04-0410-961f-82ee72b054a4
+---
+ gcc/ChangeLog          | 4 ++++
+ gcc/config/arc/arc.opt | 2 +-
+ 2 files changed, 5 insertions(+), 1 deletion(-)
+
+diff --git a/gcc/ChangeLog b/gcc/ChangeLog
+index bfda3c16668f..b3082d9135a9 100644
+--- a/gcc/ChangeLog
++++ b/gcc/ChangeLog
+@@ -1,3 +1,7 @@
++2016-06-16  Claudiu Zissulescu  <claziss at synopsys.com>
++
++	* config/arc/arc.opt (mtp-regno): Update text.
++
+ 2016-05-02  Claudiu Zissulescu  <claziss at synopsys.com>
+ 
+ 	* config/arc/arc.md (mulsidi3): Change operand 0 predicate to
+diff --git a/gcc/config/arc/arc.opt b/gcc/config/arc/arc.opt
+index 19c5deb095f7..15785498b34e 100644
+--- a/gcc/config/arc/arc.opt
++++ b/gcc/config/arc/arc.opt
+@@ -411,7 +411,7 @@ Enum(arc_fpu) String(fpud_all) Value(FPU_FPUD_ALL)
+ 
+ mtp-regno=
+ Target RejectNegative Joined UInteger Var(arc_tp_regno) Init(25)
+-Specify thread pointer register number
++Specify thread pointer register number.
+ 
+ mtp-regno=none
+ Target RejectNegative Var(arc_tp_regno,-1)
+-- 
+2.7.4
+
diff --git a/toolchain/gcc/patches/6.3.0/0032-ARC-Disable-tests-for-bare-metal.patch b/toolchain/gcc/patches/6.3.0/0032-ARC-Disable-tests-for-bare-metal.patch
new file mode 100644
index 0000000..7171177
--- /dev/null
+++ b/toolchain/gcc/patches/6.3.0/0032-ARC-Disable-tests-for-bare-metal.patch
@@ -0,0 +1,133 @@
+From f0bd3c31fc1afabece8289c42655f2582e7d393f Mon Sep 17 00:00:00 2001
+From: Claudiu Zissulescu <claziss at synopsys.com>
+Date: Fri, 17 Jun 2016 11:04:24 +0200
+Subject: [PATCH 32/89] [ARC] Disable tests for bare-metal.
+
+gcc/
+2016-06-23  Claudiu Zissulescu  <claziss at synopsys.com>
+
+	* testsuite/gcc.dg/tree-prof/time-profiler-2.c: Disable test for
+	ARC' bare-metal.
+	* testsuite/g++.dg/lto/pr69589_0.C: Likewise.
+	* testsuite/gcc.target/arc/mtune-ARC600.c: Deleted.
+	* testsuite/gcc.target/arc/mtune-ARC601.c: Likewise.
+	* testsuite/gcc.target/arc/mtune-ARC700-xmac: Likewise.
+	* testsuite/gcc.target/arc/mtune-ARC700.c: Likewise.
+	* testsuite/gcc.target/arc/mtune-ARC725D.c: Likewise.
+	* testsuite/gcc.target/arc/mtune-ARC750D.c: Likewise.
+---
+ gcc/ChangeLog                                    | 5 +++++
+ gcc/testsuite/g++.dg/lto/pr69589_0.C             | 1 +
+ gcc/testsuite/gcc.dg/tree-prof/time-profiler-2.c | 1 +
+ gcc/testsuite/gcc.target/arc/mtune-ARC600.c      | 4 ----
+ gcc/testsuite/gcc.target/arc/mtune-ARC601.c      | 4 ----
+ gcc/testsuite/gcc.target/arc/mtune-ARC700-xmac   | 4 ----
+ gcc/testsuite/gcc.target/arc/mtune-ARC700.c      | 4 ----
+ gcc/testsuite/gcc.target/arc/mtune-ARC725D.c     | 4 ----
+ gcc/testsuite/gcc.target/arc/mtune-ARC750D.c     | 4 ----
+ 9 files changed, 7 insertions(+), 24 deletions(-)
+ delete mode 100644 gcc/testsuite/gcc.target/arc/mtune-ARC600.c
+ delete mode 100644 gcc/testsuite/gcc.target/arc/mtune-ARC601.c
+ delete mode 100644 gcc/testsuite/gcc.target/arc/mtune-ARC700-xmac
+ delete mode 100644 gcc/testsuite/gcc.target/arc/mtune-ARC700.c
+ delete mode 100644 gcc/testsuite/gcc.target/arc/mtune-ARC725D.c
+ delete mode 100644 gcc/testsuite/gcc.target/arc/mtune-ARC750D.c
+
+diff --git a/gcc/ChangeLog b/gcc/ChangeLog
+index b3082d9135a9..41c1cf8278bf 100644
+--- a/gcc/ChangeLog
++++ b/gcc/ChangeLog
+@@ -1,3 +1,8 @@
++2016-06-18  Claudiu Zissulescu  <claziss at synopsys.com>
++
++	* testsuite/gcc.dg/tree-prof/time-profiler-2.c: Disable test for
++	ARC' bare-metal.
++
+ 2016-06-16  Claudiu Zissulescu  <claziss at synopsys.com>
+ 
+ 	* config/arc/arc.opt (mtp-regno): Update text.
+diff --git a/gcc/testsuite/g++.dg/lto/pr69589_0.C b/gcc/testsuite/g++.dg/lto/pr69589_0.C
+index bbdcb73dfc74..ac98cb745fb7 100644
+--- a/gcc/testsuite/g++.dg/lto/pr69589_0.C
++++ b/gcc/testsuite/g++.dg/lto/pr69589_0.C
+@@ -1,6 +1,7 @@
+ // { dg-lto-do link }
+ // { dg-lto-options "-O2 -rdynamic" } 
+ // { dg-extra-ld-options "-r -nostdlib" }
++// { dg-skip-if "" { "arc-*-elf*" } { "*" } { "" } }
+ #pragma GCC visibility push(hidden)
+ struct A { int &operator[] (long); };
+ template <typename> struct B;
+diff --git a/gcc/testsuite/gcc.dg/tree-prof/time-profiler-2.c b/gcc/testsuite/gcc.dg/tree-prof/time-profiler-2.c
+index 29c0d191afe0..d9ca7bc6132c 100644
+--- a/gcc/testsuite/gcc.dg/tree-prof/time-profiler-2.c
++++ b/gcc/testsuite/gcc.dg/tree-prof/time-profiler-2.c
+@@ -1,4 +1,5 @@
+ /* { dg-options "-O2 -fdump-ipa-profile" } */
++/* { dg-skip-if "" { "arc-*-elf*" } { "*" } { "" } } */
+ 
+ #include <unistd.h>
+ 
+diff --git a/gcc/testsuite/gcc.target/arc/mtune-ARC600.c b/gcc/testsuite/gcc.target/arc/mtune-ARC600.c
+deleted file mode 100644
+index a483d1435cae..000000000000
+--- a/gcc/testsuite/gcc.target/arc/mtune-ARC600.c
++++ /dev/null
+@@ -1,4 +0,0 @@
+-/* { dg-do compile } */
+-/* { dg-options "-mtune=ARC600" } */
+-
+-/* { dg-final { scan-assembler ".cpu ARC700" } } */
+diff --git a/gcc/testsuite/gcc.target/arc/mtune-ARC601.c b/gcc/testsuite/gcc.target/arc/mtune-ARC601.c
+deleted file mode 100644
+index ed57bd7092de..000000000000
+--- a/gcc/testsuite/gcc.target/arc/mtune-ARC601.c
++++ /dev/null
+@@ -1,4 +0,0 @@
+-/* { dg-do compile } */
+-/* { dg-options "-mtune=ARC601" } */
+-
+-/* { dg-final { scan-assembler ".cpu ARC700" } } */
+diff --git a/gcc/testsuite/gcc.target/arc/mtune-ARC700-xmac b/gcc/testsuite/gcc.target/arc/mtune-ARC700-xmac
+deleted file mode 100644
+index 2f1e137be4d4..000000000000
+--- a/gcc/testsuite/gcc.target/arc/mtune-ARC700-xmac
++++ /dev/null
+@@ -1,4 +0,0 @@
+-/* { dg-do compile } */
+-/* { dg-options "-mtune=ARC700-xmac" } */
+-
+-/* { dg-final { scan-assembler ".cpu ARC700" } } */
+diff --git a/gcc/testsuite/gcc.target/arc/mtune-ARC700.c b/gcc/testsuite/gcc.target/arc/mtune-ARC700.c
+deleted file mode 100644
+index 851ea7305e03..000000000000
+--- a/gcc/testsuite/gcc.target/arc/mtune-ARC700.c
++++ /dev/null
+@@ -1,4 +0,0 @@
+-/* { dg-do compile } */
+-/* { dg-options "-mtune=ARC700" } */
+-
+-/* { dg-final { scan-assembler ".cpu ARC700" } } */
+diff --git a/gcc/testsuite/gcc.target/arc/mtune-ARC725D.c b/gcc/testsuite/gcc.target/arc/mtune-ARC725D.c
+deleted file mode 100644
+index e2aa4846291c..000000000000
+--- a/gcc/testsuite/gcc.target/arc/mtune-ARC725D.c
++++ /dev/null
+@@ -1,4 +0,0 @@
+-/* { dg-do compile } */
+-/* { dg-options "-mtune=ARC725D" } */
+-
+-/* { dg-final { scan-assembler ".cpu ARC700" } } */
+diff --git a/gcc/testsuite/gcc.target/arc/mtune-ARC750D.c b/gcc/testsuite/gcc.target/arc/mtune-ARC750D.c
+deleted file mode 100644
+index 20923300ee12..000000000000
+--- a/gcc/testsuite/gcc.target/arc/mtune-ARC750D.c
++++ /dev/null
+@@ -1,4 +0,0 @@
+-/* { dg-do compile } */
+-/* { dg-options "-mtune=ARC750D" } */
+-
+-/* { dg-final { scan-assembler ".cpu ARC700" } } */
+-- 
+2.7.4
+
diff --git a/toolchain/gcc/patches/6.3.0/0033-ARC-Update-INSN_LENGTH_ALIGNMENT.patch b/toolchain/gcc/patches/6.3.0/0033-ARC-Update-INSN_LENGTH_ALIGNMENT.patch
new file mode 100644
index 0000000..499b1a5
--- /dev/null
+++ b/toolchain/gcc/patches/6.3.0/0033-ARC-Update-INSN_LENGTH_ALIGNMENT.patch
@@ -0,0 +1,34 @@
+From fe4dfd7c933123e3ff0f696e1a6d2766f1c9c68e Mon Sep 17 00:00:00 2001
+From: Claudiu Zissulescu <claziss at synopsys.com>
+Date: Mon, 20 Jun 2016 17:38:05 +0200
+Subject: [PATCH 33/89] [ARC] Update INSN_LENGTH_ALIGNMENT.
+
+gcc/
+2016-06-20  Claudiu Zissulescu  <claziss at synopsys.com>
+
+	* config/arc/arc.h (INSN_LENGTH_ALIGNMENT): Change.
+---
+ gcc/config/arc/arc.h | 6 +++---
+ 1 file changed, 3 insertions(+), 3 deletions(-)
+
+diff --git a/gcc/config/arc/arc.h b/gcc/config/arc/arc.h
+index 365062ede280..29f474db1b35 100644
+--- a/gcc/config/arc/arc.h
++++ b/gcc/config/arc/arc.h
+@@ -1516,10 +1516,10 @@ extern int arc_return_address_regs[4];
+ #define ASM_OUTPUT_BEFORE_CASE_LABEL(FILE, PREFIX, NUM, TABLE) \
+   ASM_OUTPUT_ALIGN ((FILE), ADDR_VEC_ALIGN (TABLE));
+ 
+-#define INSN_LENGTH_ALIGNMENT(INSN) \
+-  ((JUMP_P (INSN) \
++#define INSN_LENGTH_ALIGNMENT(INSN)		  \
++  ((JUMP_TABLE_DATA_P (INSN)			  \
+     && GET_CODE (PATTERN (INSN)) == ADDR_DIFF_VEC \
+-    && GET_MODE (PATTERN (INSN)) == QImode) \
++    && GET_MODE (PATTERN (INSN)) == QImode)	  \
+    ? 0 : length_unit_log)
+ 
+ /* Define if operations between registers always perform the operation
+-- 
+2.7.4
+
diff --git a/toolchain/gcc/patches/6.3.0/0034-ARC-Reimplement-exception-handling-support.patch b/toolchain/gcc/patches/6.3.0/0034-ARC-Reimplement-exception-handling-support.patch
new file mode 100644
index 0000000..3c42032
--- /dev/null
+++ b/toolchain/gcc/patches/6.3.0/0034-ARC-Reimplement-exception-handling-support.patch
@@ -0,0 +1,523 @@
+From a33d80531d931cc0e218e504042a98bc60a073ad Mon Sep 17 00:00:00 2001
+From: Claudiu Zissulescu <claziss at synopsys.com>
+Date: Thu, 9 Jun 2016 15:57:24 +0200
+Subject: [PATCH 34/89] [ARC] Reimplement exception handling support.
+
+2016-06-09  Claudiu Zissulescu  <claziss at synopsys.com>
+	    Andrew Burgess  <andrew.burgess at embecosm.com>
+
+	* config/arc/arc-protos.h (arc_compute_frame_size): Delete
+	declaration.
+	(arc_return_slot_offset): Likewise.
+	(arc_eh_return_address_location): New declaration.
+	* config/arc/arc.c (TARGET_BUILTIN_SETJMP_FRAME_VALUE): Define.
+	(MUST_SAVE_REGISTER): Add exception handler case.
+	(MUST_SAVE_RETURN_ADDR): Likewise.
+	(arc_frame_pointer_required): Likewise.
+	(arc_frame_pointer_needed): New function.
+	(arc_compute_frame_size): Changed.
+	(arc_expand_prologue): Likewise.
+	(arc_expand_epilogue): Likewise.
+	(arc_initial_elimination_offset): Likewise.
+	(arc_return_slot_offset): Delete.
+	(arc_eh_return_address_location): New function.
+	(arc_builtin_setjmp_frame_value): Likewise.
+	* config/arc/arc.h (EH_RETURN_DATA_REGNO): Use 2 registers.
+	(EH_RETURN_STACKADJ_RTX): Define.
+	(EH_RETURN_HANDLER_RTX): Likewise.
+	* config/arc/arc.md (eh_return): Delete.
+---
+ gcc/config/arc/arc-protos.h |   4 +-
+ gcc/config/arc/arc.c        | 249 +++++++++++++++++++++++++++++++++++---------
+ gcc/config/arc/arc.h        |   7 +-
+ gcc/config/arc/arc.md       |  33 ------
+ 4 files changed, 204 insertions(+), 89 deletions(-)
+
+diff --git a/gcc/config/arc/arc-protos.h b/gcc/config/arc/arc-protos.h
+index 0e9476699ee3..892b15ede31a 100644
+--- a/gcc/config/arc/arc-protos.h
++++ b/gcc/config/arc/arc-protos.h
+@@ -51,8 +51,6 @@ extern bool compact_memory_operand_p (rtx, machine_mode, bool, bool);
+ extern enum arc_function_type arc_compute_function_type (struct function *);
+ #endif /* TREE_CODE */
+ 
+-
+-extern unsigned int arc_compute_frame_size (int);
+ extern bool arc_ccfsm_branch_deleted_p (void);
+ extern void arc_ccfsm_record_branch_deleted (void);
+ 
+@@ -118,8 +116,8 @@ extern bool arc_epilogue_uses (int regno);
+ extern bool arc_eh_uses (int regno);
+ /* insn-attrtab.c doesn't include reload.h, which declares regno_clobbered_p. */
+ extern int regno_clobbered_p (unsigned int, rtx_insn *, machine_mode, int);
+-extern int arc_return_slot_offset (void);
+ extern bool arc_legitimize_reload_address (rtx *, machine_mode, int, int);
+ extern void arc_secondary_reload_conv (rtx, rtx, rtx, bool);
+ extern bool insn_is_tls_gd_dispatch (rtx_insn *);
+ extern void arc_cpu_cpp_builtins (cpp_reader *);
++extern rtx arc_eh_return_address_location (void);
+diff --git a/gcc/config/arc/arc.c b/gcc/config/arc/arc.c
+index c2673334db5d..0c3ee90febcd 100644
+--- a/gcc/config/arc/arc.c
++++ b/gcc/config/arc/arc.c
+@@ -475,6 +475,9 @@ static void arc_finalize_pic (void);
+ #undef TARGET_DWARF_REGISTER_SPAN
+ #define TARGET_DWARF_REGISTER_SPAN arc_dwarf_register_span
+ 
++#undef TARGET_BUILTIN_SETJMP_FRAME_VALUE
++#define TARGET_BUILTIN_SETJMP_FRAME_VALUE arc_builtin_setjmp_frame_value
++
+ /* Try to keep the (mov:DF _, reg) as early as possible so
+    that the d<add/sub/mul>h-lr insns appear together and can
+    use the peephole2 pattern.  */
+@@ -2171,15 +2174,80 @@ arc_compute_function_type (struct function *fun)
+    function changes it to access gotoff variables.
+    FIXME: This will not be needed if we used some arbitrary register
+    instead of r26.
+-*/
+-#define MUST_SAVE_REGISTER(regno, interrupt_p) \
+-(((regno) != RETURN_ADDR_REGNUM && (regno) != FRAME_POINTER_REGNUM \
+-  && (df_regs_ever_live_p (regno) && (!call_used_regs[regno] || interrupt_p))) \
+- || (flag_pic && crtl->uses_pic_offset_table \
+-     && regno == PIC_OFFSET_TABLE_REGNUM) )
+ 
+-#define MUST_SAVE_RETURN_ADDR \
+-  (cfun->machine->frame_info.save_return_addr)
++   In frames that call __builtin_eh_return we should spill more
++   registers, this allows that stack unwinding code to access values
++   that are held in these registers (the stack unwinding
++   implementation only looks for register values on the stack, never,
++   in the actual register).
++
++   However, we don't include the data registers, or the stack
++   adjustment registers here (0, 1, 2).  The data registers are
++   covered by their own specific logic in the save/restore code, while
++   the stack adjustment register should not be restored.
++
++   It's probably the case that we don't need to spill any of the
++   caller saved registers in this logic, but for now I'm leaving the
++   code like this.  The number of frames that use __builtin_eh_return
++   is pretty low, so optimising them is not critical right now.  */
++
++#define MUST_SAVE_REGISTER(regno, interrupt_p)				\
++  (((regno) != RETURN_ADDR_REGNUM && (regno) != FRAME_POINTER_REGNUM	\
++    && (df_regs_ever_live_p (regno)					\
++	&& (!call_used_regs[regno] || interrupt_p)))			\
++   || (flag_pic && crtl->uses_pic_offset_table				\
++       && regno == PIC_OFFSET_TABLE_REGNUM)				\
++   || (crtl->calls_eh_return && (regno > 2 && regno < 27)))
++
++#define MUST_SAVE_RETURN_ADDR	(cfun->machine->frame_info.save_return_addr)
++
++/* Helper function to wrap FRAME_POINTER_NEEDED.  We do this as
++   FRAME_POINTER_NEEDED will not be true until the IRA (Integrated
++   Register Allocator) pass, while we want to get the frame size
++   correct earlier than the IRA pass.
++
++   When a function uses eh_return we must ensure that the fp register
++   is saved and then restored so that the unwinder can restore the
++   correct value for the frame we are going to jump to.
++
++   To do this we force all frames that call eh_return to require a
++   frame pointer (see changes to arc_frame_pointer_required), this
++   will ensure that the previous frame pointer is stored on entry to
++   the function, and will then be reloaded at function exit.
++
++   As the frame pointer is handled as a special case in our prologue
++   and epilogue code it must not be saved and restored using the
++   MUST_SAVE_REGISTER mechanism otherwise we run into issues where GCC
++   believes that the function is not using a frame pointer and that
++   the value in the fp register is the frame pointer, while the
++   prologue and epilogue are busy saving and restoring the fp
++   register.  This issue is fixed in this commit too.
++
++   During compilation of a function the frame size is evaluated
++   multiple times, it is not until the reload pass is complete the the
++   frame size is considered fixed (it is at this point that space for
++   all spills has been allocated).  However the frame_pointer_needed
++   variable is not set true until the register allocation pass, as a
++   result in the early stages the frame size does not include space
++   for the frame pointer to be spilled.
++
++   The problem that this causes, that I have not yet tracked down, is
++   that the rtl generated for EH_RETURN_HANDLER_RTX uses the details
++   of the frame size to compute the offset from the frame pointer at
++   which the return address lives.  However, in early passes GCC has
++   not yet realised we need a frame pointer, and so has not included
++   space for the frame pointer in the frame size, and so gets the
++   offset of the return address wrong.  This should not be an issue as
++   in later passes GCC has realised that the frame pointer needs to be
++   spilled, and has increased the frame size.  However, the rtl for
++   the EH_RETURN_HANDLER_RTX is not regenerated to use the newer,
++   larger offset, and the wrong smaller offset is used.  */
++
++static bool
++arc_frame_pointer_needed (void)
++{
++  return (frame_pointer_needed || crtl->calls_eh_return);
++}
+ 
+ /* Return non-zero if there are registers to be saved or loaded using
+    millicode thunks.  We can only use consecutive sequences starting
+@@ -2211,13 +2279,11 @@ arc_compute_millicode_save_restore_regs (unsigned int gmask,
+   return 0;
+ }
+ 
+-/* Return the bytes needed to compute the frame pointer from the current
+-   stack pointer.
+-
+-   SIZE is the size needed for local variables.  */
++/* Return the bytes needed to compute the frame pointer from the
++   current stack pointer.  */
+ 
+-unsigned int
+-arc_compute_frame_size (int size)	/* size = # of var. bytes allocated.  */
++static unsigned int
++arc_compute_frame_size (void)
+ {
+   int regno;
+   unsigned int total_size, var_size, args_size, pretend_size, extra_size;
+@@ -2225,14 +2291,20 @@ arc_compute_frame_size (int size)	/* size = # of var. bytes allocated.  */
+   unsigned int gmask;
+   enum arc_function_type fn_type;
+   int interrupt_p;
+-  struct arc_frame_info *frame_info = &cfun->machine->frame_info;
++  struct arc_frame_info *frame_info;
++  int size;
++
++  /* The answer might already be known.  */
++  if (cfun->machine->frame_info.initialized)
++    return cfun->machine->frame_info.total_size;
+ 
+-  size = ARC_STACK_ALIGN (size);
++  frame_info = &cfun->machine->frame_info;
++  size = ARC_STACK_ALIGN (get_frame_size ());
+ 
+-  /* 1) Size of locals and temporaries */
++  /* 1) Size of locals and temporaries.  */
+   var_size	= size;
+ 
+-  /* 2) Size of outgoing arguments */
++  /* 2) Size of outgoing arguments.  */
+   args_size	= crtl->outgoing_args_size;
+ 
+   /* 3) Calculate space needed for saved registers.
+@@ -2255,12 +2327,29 @@ arc_compute_frame_size (int size)	/* size = # of var. bytes allocated.  */
+ 	}
+     }
+ 
++  /* In a frame that calls __builtin_eh_return two data registers are
++     used to pass values back to the exception handler.
++
++     Ensure that these registers are spilled to the stack so that the
++     exception throw code can find them, and update the saved values.
++     The handling code will then consume these reloaded values to
++     handle the exception.  */
++  if (crtl->calls_eh_return)
++    for (regno = 0; EH_RETURN_DATA_REGNO (regno) != INVALID_REGNUM; regno++)
++      {
++	reg_size += UNITS_PER_WORD;
++	gmask |= 1 << regno;
++      }
++
+   /* 4) Space for back trace data structure.
+ 	<return addr reg size> (if required) + <fp size> (if required).  */
+   frame_info->save_return_addr
+-    = (!crtl->is_leaf || df_regs_ever_live_p (RETURN_ADDR_REGNUM));
++    = (!crtl->is_leaf || df_regs_ever_live_p (RETURN_ADDR_REGNUM)
++       || crtl->calls_eh_return);
+   /* Saving blink reg in case of leaf function for millicode thunk calls.  */
+-  if (optimize_size && !TARGET_NO_MILLICODE_THUNK_SET)
++  if (optimize_size
++      && !TARGET_NO_MILLICODE_THUNK_SET
++      && !crtl->calls_eh_return)
+     {
+       if (arc_compute_millicode_save_restore_regs (gmask, frame_info))
+ 	frame_info->save_return_addr = true;
+@@ -2269,7 +2358,7 @@ arc_compute_frame_size (int size)	/* size = # of var. bytes allocated.  */
+   extra_size = 0;
+   if (MUST_SAVE_RETURN_ADDR)
+     extra_size = 4;
+-  if (frame_pointer_needed)
++  if (arc_frame_pointer_needed ())
+     extra_size += 4;
+ 
+   /* 5) Space for variable arguments passed in registers */
+@@ -2288,13 +2377,17 @@ arc_compute_frame_size (int size)	/* size = # of var. bytes allocated.  */
+   /* Compute total frame size.  */
+   total_size = var_size + args_size + extra_size + pretend_size + reg_size;
+ 
+-  total_size = ARC_STACK_ALIGN (total_size);
++  /* It used to be the case that the alignment was forced at this
++     point.  However, that is dangerous, calculations based on
++     total_size would be wrong.  Given that this has never cropped up
++     as an issue I've changed this to an assert for now.  */
++  gcc_assert (total_size == ARC_STACK_ALIGN (total_size));
+ 
+   /* Compute offset of register save area from stack pointer:
+      Frame: pretend_size <blink> reg_size <fp> var_size args_size <--sp
+   */
+   reg_offset = (total_size - (pretend_size + reg_size + extra_size)
+-		+ (frame_pointer_needed ? 4 : 0));
++		+ (arc_frame_pointer_needed ()? 4 : 0));
+ 
+   /* Save computed information.  */
+   frame_info->total_size   = total_size;
+@@ -2490,7 +2583,7 @@ int arc_return_address_regs[4]
+ void
+ arc_expand_prologue (void)
+ {
+-  int size = get_frame_size ();
++  int size;
+   unsigned int gmask = cfun->machine->frame_info.gmask;
+   /*  unsigned int frame_pointer_offset;*/
+   unsigned int frame_size_to_allocate;
+@@ -2499,12 +2592,8 @@ arc_expand_prologue (void)
+      PRE_MODIFY, thus enabling more short insn generation.)  */
+   int first_offset = 0;
+ 
+-  size = ARC_STACK_ALIGN (size);
+-
+-  /* Compute/get total frame size.  */
+-  size = (!cfun->machine->frame_info.initialized
+-	   ? arc_compute_frame_size (size)
+-	   : cfun->machine->frame_info.total_size);
++  /* Compute total frame size.  */
++  size = arc_compute_frame_size ();
+ 
+   if (flag_stack_usage_info)
+     current_function_static_stack_size = size;
+@@ -2548,7 +2637,7 @@ arc_expand_prologue (void)
+ 
+ 
+   /* Save frame pointer if needed.  */
+-  if (frame_pointer_needed)
++  if (arc_frame_pointer_needed ())
+     {
+       rtx addr = gen_rtx_PLUS (Pmode, stack_pointer_rtx,
+ 			       GEN_INT (-UNITS_PER_WORD + first_offset));
+@@ -2583,13 +2672,10 @@ arc_expand_prologue (void)
+ void
+ arc_expand_epilogue (int sibcall_p)
+ {
+-  int size = get_frame_size ();
++  int size;
+   enum arc_function_type fn_type = arc_compute_function_type (cfun);
+ 
+-  size = ARC_STACK_ALIGN (size);
+-  size = (!cfun->machine->frame_info.initialized
+-	   ? arc_compute_frame_size (size)
+-	   : cfun->machine->frame_info.total_size);
++  size = arc_compute_frame_size ();
+ 
+   unsigned int pretend_size = cfun->machine->frame_info.pretend_size;
+   unsigned int frame_size;
+@@ -2612,13 +2698,13 @@ arc_expand_epilogue (int sibcall_p)
+      sp, but don't restore sp if we don't have to.  */
+ 
+   if (!can_trust_sp_p)
+-    gcc_assert (frame_pointer_needed);
++    gcc_assert (arc_frame_pointer_needed ());
+ 
+   /* Restore stack pointer to the beginning of saved register area for
+      ARCompact ISA.  */
+   if (frame_size)
+     {
+-      if (frame_pointer_needed)
++      if (arc_frame_pointer_needed ())
+ 	frame_move (stack_pointer_rtx, frame_pointer_rtx);
+       else
+ 	first_offset = frame_size;
+@@ -2629,7 +2715,7 @@ arc_expand_epilogue (int sibcall_p)
+ 
+ 
+   /* Restore any saved registers.  */
+-  if (frame_pointer_needed)
++  if (arc_frame_pointer_needed ())
+     {
+       rtx addr = gen_rtx_POST_INC (Pmode, stack_pointer_rtx);
+ 
+@@ -2752,21 +2838,59 @@ arc_expand_epilogue (int sibcall_p)
+   if (size > restored)
+     frame_stack_add (size - restored);
+ 
++  /* For frames that use __builtin_eh_return, the register defined by
++     EH_RETURN_STACKADJ_RTX is set to 0 for all standard return paths.
++     On eh_return paths however, the register is set to the value that
++     should be added to the stack pointer in order to restore the
++     correct stack pointer for the exception handling frame.
++
++     For ARC we are going to use r2 for EH_RETURN_STACKADJ_RTX, add
++     this onto the stack for eh_return frames.  */
++  if (crtl->calls_eh_return)
++    emit_insn (gen_add2_insn (stack_pointer_rtx,
++			      EH_RETURN_STACKADJ_RTX));
++
+   /* Emit the return instruction.  */
+   if (sibcall_p == FALSE)
+     emit_jump_insn (gen_simple_return ());
+ }
+ 
+-/* Return the offset relative to the stack pointer where the return address
+-   is stored, or -1 if it is not stored.  */
+-
+-int
+-arc_return_slot_offset ()
+-{
+-  struct arc_frame_info *afi = &cfun->machine->frame_info;
++/* Return rtx for the location of the return address on the stack,
++   suitable for use in __builtin_eh_return.  The new return address
++   will be written to this location in order to redirect the return to
++   the exception handler.  */
+ 
+-  return (afi->save_return_addr
+-	  ? afi->total_size - afi->pretend_size - afi->extra_size : -1);
++rtx
++arc_eh_return_address_location (void)
++{
++  rtx mem;
++  int offset;
++  struct arc_frame_info *afi;
++
++  arc_compute_frame_size ();
++  afi = &cfun->machine->frame_info;
++
++  gcc_assert (crtl->calls_eh_return);
++  gcc_assert (afi->save_return_addr);
++  gcc_assert (afi->extra_size >= 4);
++
++  /* The '-4' removes the size of the return address, which is
++     included in the 'extra_size' field.  */
++  offset = afi->reg_size + afi->extra_size - 4;
++  mem = gen_frame_mem (Pmode,
++		       plus_constant (Pmode, frame_pointer_rtx, offset));
++
++  /* The following should not be needed, and is, really a hack.  The
++     issue being worked around here is that the DSE (Dead Store
++     Elimination) pass will remove this write to the stack as it sees
++     a single store and no corresponding read.  The read however
++     occurs in the epilogue code, which is not added into the function
++     rtl until a later pass.  So, at the time of DSE, the decision to
++     remove this store seems perfectly sensible.  Marking the memory
++     address as volatile obviously has the effect of preventing DSE
++     from removing the store.  */
++  MEM_VOLATILE_P (mem) = 1;
++  return mem;
+ }
+ 
+ /* PIC */
+@@ -4320,8 +4444,8 @@ arc_can_eliminate (const int from ATTRIBUTE_UNUSED, const int to)
+ int
+ arc_initial_elimination_offset (int from, int to)
+ {
+-  if (! cfun->machine->frame_info.initialized)
+-     arc_compute_frame_size (get_frame_size ());
++  if (!cfun->machine->frame_info.initialized)
++    arc_compute_frame_size ();
+ 
+   if (from == ARG_POINTER_REGNUM && to == FRAME_POINTER_REGNUM)
+     {
+@@ -4349,7 +4473,7 @@ arc_initial_elimination_offset (int from, int to)
+ static bool
+ arc_frame_pointer_required (void)
+ {
+- return cfun->calls_alloca;
++ return cfun->calls_alloca || crtl->calls_eh_return;
+ }
+ 
+ 
+@@ -10059,6 +10183,29 @@ compact_memory_operand_p (rtx op, machine_mode mode,
+   return false;
+ }
+ 
++
++/* Return the frame pointer value to be backed up in the setjmp buffer.  */
++
++static rtx
++arc_builtin_setjmp_frame_value (void)
++{
++  /* We always want to preserve whatever value is currently in the frame
++     pointer register.  For frames that are using the frame pointer the new
++     value of the frame pointer register will have already been computed
++     (as part of the prologue).  For frames that are not using the frame
++     pointer it is important that we backup whatever value is in the frame
++     pointer register, as earlier (more outer) frames may have placed a
++     value into the frame pointer register.  It might be tempting to try
++     and use `frame_pointer_rtx` here, however, this is not what we want.
++     For frames that are using the frame pointer this will give the
++     correct value.  However, for frames that are not using the frame
++     pointer this will still give the value that _would_ have been the
++     frame pointer value for this frame (if the use of the frame pointer
++     had not been removed).  We really do want the raw frame pointer
++     register value.  */
++  return gen_raw_REG (Pmode, FRAME_POINTER_REGNUM);
++}
++
+ struct gcc_target targetm = TARGET_INITIALIZER;
+ 
+ #include "gt-arc.h"
+diff --git a/gcc/config/arc/arc.h b/gcc/config/arc/arc.h
+index 29f474db1b35..d2adf4d8f1bb 100644
+--- a/gcc/config/arc/arc.h
++++ b/gcc/config/arc/arc.h
+@@ -1474,8 +1474,11 @@ extern int arc_return_address_regs[4];
+ #define DWARF2_UNWIND_INFO 0
+ #endif
+ 
+-#define EH_RETURN_DATA_REGNO(N)	\
+-  ((N) < 4 ? (N) : INVALID_REGNUM)
++#define EH_RETURN_DATA_REGNO(N)  ((N) < 2 ? (N) : INVALID_REGNUM)
++
++#define EH_RETURN_STACKADJ_RTX   gen_rtx_REG (Pmode, 2)
++
++#define EH_RETURN_HANDLER_RTX    arc_eh_return_address_location ()
+ 
+ /* Turn off splitting of long stabs.  */
+ #define DBX_CONTIN_LENGTH 0
+diff --git a/gcc/config/arc/arc.md b/gcc/config/arc/arc.md
+index 64afb8bf7bf6..7d9d232e7e61 100644
+--- a/gcc/config/arc/arc.md
++++ b/gcc/config/arc/arc.md
+@@ -4828,39 +4828,6 @@
+ 	       (const_int 4)]
+ 	      (const_int 2)))])
+ 
+-(define_insn_and_split "eh_return"
+-  [(eh_return)
+-   (use (match_operand:SI 0 "move_src_operand" "rC32,mCalCpc"))
+-   (clobber (match_scratch:SI 1  "=X,r"))
+-   (clobber (match_scratch:SI 2 "=&r,r"))]
+-  ""
+-  "#"
+-  "reload_completed"
+-  [(set (match_dup 2) (match_dup 0))]
+-{
+-  int offs = arc_return_slot_offset ();
+-
+-  if (offs < 0)
+-    operands[2] = gen_rtx_REG (Pmode, RETURN_ADDR_REGNUM);
+-  else
+-    {
+-      if (!register_operand (operands[0], Pmode)
+-	  && !satisfies_constraint_C32 (operands[0]))
+-	{
+-	  emit_move_insn (operands[1], operands[0]);
+-	  operands[0] = operands[1];
+-	}
+-      rtx addr = plus_constant (Pmode, stack_pointer_rtx, offs);
+-      if (!strict_memory_address_p (Pmode, addr))
+-	{
+-	  emit_move_insn (operands[2], addr);
+-	  addr = operands[2];
+-	}
+-      operands[2] = gen_frame_mem (Pmode, addr);
+-    }
+-}
+-  [(set_attr "length" "12")])
+-
+ ;; ??? #ifdefs in function.c require the presence of this pattern, with a
+ ;; non-constant predicate.
+ (define_expand "return"
+-- 
+2.7.4
+
diff --git a/toolchain/gcc/patches/6.3.0/0035-ARC-Fix-mul32x16-patterns.patch b/toolchain/gcc/patches/6.3.0/0035-ARC-Fix-mul32x16-patterns.patch
new file mode 100644
index 0000000..1961ba9
--- /dev/null
+++ b/toolchain/gcc/patches/6.3.0/0035-ARC-Fix-mul32x16-patterns.patch
@@ -0,0 +1,56 @@
+From 9743f5d060948aea986456cdfa07fc11e20e3727 Mon Sep 17 00:00:00 2001
+From: Claudiu Zissulescu <claziss at synopsys.com>
+Date: Tue, 28 Jun 2016 15:05:17 +0200
+Subject: [PATCH 35/89] [ARC] Fix mul32x16 patterns.
+
+gcc/
+2016-06-28  Claudiu Zissulescu  <claziss at synopsys.com>
+
+	* config/arc/arc.md (umul_600): Change.
+	(umul64_600): Likewise.
+---
+ gcc/config/arc/arc.md | 18 +++++++-----------
+ 1 file changed, 7 insertions(+), 11 deletions(-)
+
+diff --git a/gcc/config/arc/arc.md b/gcc/config/arc/arc.md
+index 7d9d232e7e61..7d6d1fcfaefe 100644
+--- a/gcc/config/arc/arc.md
++++ b/gcc/config/arc/arc.md
+@@ -1937,13 +1937,11 @@
+ 				  (const_int 0))))
+    (clobber (match_operand:SI 3 "acc1_operand" ""))]
+   "TARGET_MULMAC_32BY16_SET"
+-  "@mululw 0, %0, %1
+-    mululw 0, %0, %1
+-    mululw%? 0, %1, %0"
++  "mululw 0, %0, %1"
+   [(set_attr "length" "4,4,8")
+-   (set_attr "type" "mulmac_600, mulmac_600, mulmac_600")
+-   (set_attr "predicable" "no, no, yes")
+-   (set_attr "cond" "nocond, canuse_limm, canuse")])
++   (set_attr "type" "mulmac_600")
++   (set_attr "predicable" "no")
++   (set_attr "cond" "nocond")])
+ 
+ (define_insn "mac_600"
+   [(set (match_operand:SI 2 "acc2_operand" "")
+@@ -2372,13 +2370,11 @@
+ 				  (const_int 0))))
+   ]
+   "TARGET_MULMAC_32BY16_SET"
+-  "@mululw 0, %0, %1
+-    mululw 0, %0, %1
+-    mululw%? 0, %1, %0"
++  "mululw 0, %0, %1"
+   [(set_attr "length" "4,4,8")
+    (set_attr "type" "mulmac_600")
+-   (set_attr "predicable" "no,no,yes")
+-   (set_attr "cond" "nocond, canuse_limm, canuse")])
++   (set_attr "predicable" "no")
++   (set_attr "cond" "nocond")])
+ 
+ 
+ (define_insn "umac64_600"
+-- 
+2.7.4
+
diff --git a/toolchain/gcc/patches/6.3.0/0036-ARC-Cleanup-implementation.patch b/toolchain/gcc/patches/6.3.0/0036-ARC-Cleanup-implementation.patch
new file mode 100644
index 0000000..26218d7
--- /dev/null
+++ b/toolchain/gcc/patches/6.3.0/0036-ARC-Cleanup-implementation.patch
@@ -0,0 +1,201 @@
+From f5bcabb00a01fa1aa4abb2254493fb44f23a9975 Mon Sep 17 00:00:00 2001
+From: Claudiu Zissulescu <claziss at synopsys.com>
+Date: Thu, 30 Jun 2016 12:19:27 +0200
+Subject: [PATCH 36/89] [ARC] Cleanup implementation.
+
+gcc/
+2016-06-30  Claudiu Zissulescu  <claziss at synopsys.com>
+
+	* config/arc/arc-protos.h (insn_is_tls_gd_dispatch): Remove.
+	* config/arc/arc.c (arc_unspec_offset): New function.
+	(arc_finalize_pic): Change.
+	(arc_emit_call_tls_get_addr): Likewise.
+	(arc_legitimize_tls_address): Likewise.
+	(arc_legitimize_pic_address): Likewise.
+	(insn_is_tls_gd_dispatch): Remove.
+	* config/arc/arc.h (INSN_REFERENCES_ARE_DELAYED): Change.
+	* config/arc/arc.md (ls_gd_load): Remove.
+	(tls_gd_dispatch): Likewise.
+---
+ gcc/config/arc/arc-protos.h |  1 -
+ gcc/config/arc/arc.c        | 41 ++++++++++++++++++-----------------------
+ gcc/config/arc/arc.h        |  2 +-
+ gcc/config/arc/arc.md       | 34 ----------------------------------
+ 4 files changed, 19 insertions(+), 59 deletions(-)
+
+diff --git a/gcc/config/arc/arc-protos.h b/gcc/config/arc/arc-protos.h
+index 892b15ede31a..ffc715f2e82a 100644
+--- a/gcc/config/arc/arc-protos.h
++++ b/gcc/config/arc/arc-protos.h
+@@ -118,6 +118,5 @@ extern bool arc_eh_uses (int regno);
+ extern int regno_clobbered_p (unsigned int, rtx_insn *, machine_mode, int);
+ extern bool arc_legitimize_reload_address (rtx *, machine_mode, int, int);
+ extern void arc_secondary_reload_conv (rtx, rtx, rtx, bool);
+-extern bool insn_is_tls_gd_dispatch (rtx_insn *);
+ extern void arc_cpu_cpp_builtins (cpp_reader *);
+ extern rtx arc_eh_return_address_location (void);
+diff --git a/gcc/config/arc/arc.c b/gcc/config/arc/arc.c
+index 0c3ee90febcd..b0b21ad8b59f 100644
+--- a/gcc/config/arc/arc.c
++++ b/gcc/config/arc/arc.c
+@@ -2895,6 +2895,15 @@ arc_eh_return_address_location (void)
+ 
+ /* PIC */
+ 
++/* Helper to generate unspec constant.  */
++
++static rtx
++arc_unspec_offset (rtx loc, int unspec)
++{
++  return gen_rtx_CONST (Pmode, gen_rtx_UNSPEC (Pmode, gen_rtvec (1, loc),
++					       unspec));
++}
++
+ /* Emit special PIC prologues and epilogues.  */
+ /* If the function has any GOTOFF relocations, then the GOTBASE
+    register has to be setup in the prologue
+@@ -2920,9 +2929,7 @@ arc_finalize_pic (void)
+   gcc_assert (flag_pic != 0);
+ 
+   pat = gen_rtx_SYMBOL_REF (Pmode, "_DYNAMIC");
+-  pat = gen_rtx_UNSPEC (Pmode, gen_rtvec (1, pat), ARC_UNSPEC_GOT);
+-  pat = gen_rtx_CONST (Pmode, pat);
+-
++  pat = arc_unspec_offset (pat, ARC_UNSPEC_GOT);
+   pat = gen_rtx_SET (baseptr_rtx, pat);
+ 
+   emit_insn (pat);
+@@ -4991,8 +4998,7 @@ arc_emit_call_tls_get_addr (rtx sym, int reloc, rtx eqv)
+ 
+   start_sequence ();
+ 
+-  rtx x = gen_rtx_UNSPEC (Pmode, gen_rtvec (1, sym), reloc);
+-  x = gen_rtx_CONST (Pmode, x);
++  rtx x = arc_unspec_offset (sym, reloc);
+   emit_move_insn (r0, x);
+   use_reg (&call_fusage, r0);
+ 
+@@ -5048,17 +5054,18 @@ arc_legitimize_tls_address (rtx addr, enum tls_model model)
+       addr = gen_rtx_CONST (Pmode, addr);
+       base = arc_legitimize_tls_address (base, TLS_MODEL_GLOBAL_DYNAMIC);
+       return gen_rtx_PLUS (Pmode, force_reg (Pmode, base), addr);
++
+     case TLS_MODEL_GLOBAL_DYNAMIC:
+       return arc_emit_call_tls_get_addr (addr, UNSPEC_TLS_GD, addr);
++
+     case TLS_MODEL_INITIAL_EXEC:
+-      addr = gen_rtx_UNSPEC (Pmode, gen_rtvec (1, addr), UNSPEC_TLS_IE);
+-      addr = gen_rtx_CONST (Pmode, addr);
++      addr = arc_unspec_offset (addr, UNSPEC_TLS_IE);
+       addr = copy_to_mode_reg (Pmode, gen_const_mem (Pmode, addr));
+       return gen_rtx_PLUS (Pmode, arc_get_tp (), addr);
++
+     case TLS_MODEL_LOCAL_EXEC:
+     local_exec:
+-      addr = gen_rtx_UNSPEC (Pmode, gen_rtvec (1, addr), UNSPEC_TLS_OFF);
+-      addr = gen_rtx_CONST (Pmode, addr);
++      addr = arc_unspec_offset (addr, UNSPEC_TLS_OFF);
+       return gen_rtx_PLUS (Pmode, arc_get_tp (), addr);
+     default:
+       gcc_unreachable ();
+@@ -5089,14 +5096,11 @@ arc_legitimize_pic_address (rtx orig, rtx oldx)
+       else if (!flag_pic)
+ 	return orig;
+       else if (CONSTANT_POOL_ADDRESS_P (addr) || SYMBOL_REF_LOCAL_P (addr))
+-	return gen_rtx_CONST (Pmode,
+-			      gen_rtx_UNSPEC (Pmode, gen_rtvec (1, addr),
+-			      ARC_UNSPEC_GOTOFFPC));
++	return arc_unspec_offset (addr, ARC_UNSPEC_GOTOFFPC);
+ 
+       /* This symbol must be referenced via a load from the Global
+ 	 Offset Table (@GOTPC).  */
+-      pat = gen_rtx_UNSPEC (Pmode, gen_rtvec (1, addr), ARC_UNSPEC_GOT);
+-      pat = gen_rtx_CONST (Pmode, pat);
++      pat = arc_unspec_offset (addr, ARC_UNSPEC_GOT);
+       pat = gen_const_mem (Pmode, pat);
+ 
+       if (oldx == NULL)
+@@ -10034,15 +10038,6 @@ arc_dwarf_register_span (rtx rtl)
+    return p;
+ }
+ 
+-/* We can't inline this in INSN_REFERENCES_ARE_DELAYED because
+-   resource.h doesn't include the required header files.  */
+-
+-bool
+-insn_is_tls_gd_dispatch (rtx_insn *insn)
+-{
+-  return recog_memoized (insn) == CODE_FOR_tls_gd_dispatch;
+-}
+-
+ /* Return true if OP is an acceptable memory operand for ARCompact
+    16-bit load instructions of MODE.
+ 
+diff --git a/gcc/config/arc/arc.h b/gcc/config/arc/arc.h
+index d2adf4d8f1bb..6a579eba014c 100644
+--- a/gcc/config/arc/arc.h
++++ b/gcc/config/arc/arc.h
+@@ -1617,7 +1617,7 @@ extern enum arc_function_type arc_compute_function_type (struct function *);
+    && (get_attr_type (X) == TYPE_CALL || get_attr_type (X) == TYPE_SFUNC))
+ 
+ #define INSN_REFERENCES_ARE_DELAYED(insn)				\
+-  (INSN_SETS_ARE_DELAYED (insn) && !insn_is_tls_gd_dispatch (insn))
++  (INSN_SETS_ARE_DELAYED (insn))
+ 
+ #define CALL_ATTR(X, NAME) \
+   ((CALL_P (X) || NONJUMP_INSN_P (X)) \
+diff --git a/gcc/config/arc/arc.md b/gcc/config/arc/arc.md
+index 7d6d1fcfaefe..f9080fb1eb48 100644
+--- a/gcc/config/arc/arc.md
++++ b/gcc/config/arc/arc.md
+@@ -5394,21 +5394,6 @@
+   [(set_attr "is_sfunc" "yes")
+    (set_attr "predicable" "yes")])
+ 
+-(define_insn "tls_gd_load"
+-  [(set (match_operand:SI 0 "dest_reg_operand" "=Rcq#q,c")
+-	(unspec:SI [(match_operand:SI 1 "register_operand" "Rcq#q,c")
+-		    (match_operand:SI 2 "symbolic_operand" "X,X")]
+-	 UNSPEC_TLS_GD))]
+-  ""
+-  ".tls_gd_ld %2`ld%? %0,[%1]"
+-  [(set_attr "type" "load")
+-   ; if the linker has to patch this into IE, we need a long insn
+-   ; (FIXME: or two short insn, ld_s / jl_s.  missing -Os optimization.)
+-   (set_attr_alternative "iscompact"
+-     [(cond [(ne (symbol_ref "arc_tp_regno == 30") (const_int 0))
+-	     (const_string "*")] (const_string "maybe"))
+-      (const_string "*")])])
+-
+ (define_insn "tls_gd_get_addr"
+   [(set (reg:SI R0_REG)
+ 	(call:SI (mem:SI (unspec:SI [(match_operand:SI 0
+@@ -5422,25 +5407,6 @@
+    ; With TARGET_MEDIUM_CALLS, plt calls are not predicable.
+    (set_attr "predicable" "no")])
+ 
+-; We make this call specific to the tls symbol to avoid commoning this
+-; with calls for other symbols; we want the linker to be able to
+-(define_insn "tls_gd_dispatch"
+-  [(set (reg:SI R0_REG)
+-	(unspec:SI
+-	  [(reg:SI R0_REG)
+-	   (call (mem:SI (match_operand:SI 0 "register_operand" "Rcq,q,c"))
+-		 (const_int 0))
+-	   (match_operand:SI 1 "symbolic_operand" "X,X,X")]
+-	 UNSPEC_TLS_GD))
+-   (clobber (reg:SI RETURN_ADDR_REGNUM))
+-   (clobber (reg:DI R10_REG))
+-   (clobber (reg:SI R12_REG))]
+-  ""
+-  ".tls_gd_call %1`jl%!%* [%0]"
+-  [(set_attr "type" "call")
+-   (set_attr "iscompact" "maybe,false,*")
+-   (set_attr "predicable" "no,no,yes")])
+-
+ ;; For thread pointer builtins
+ (define_expand "get_thread_pointersi"
+   [(set (match_operand:SI 0 "register_operand") (match_dup 1))]
+-- 
+2.7.4
+
diff --git a/toolchain/gcc/patches/6.3.0/0037-ARC-Refurbish-mul64-support.patch b/toolchain/gcc/patches/6.3.0/0037-ARC-Refurbish-mul64-support.patch
new file mode 100644
index 0000000..ddf03ad
--- /dev/null
+++ b/toolchain/gcc/patches/6.3.0/0037-ARC-Refurbish-mul64-support.patch
@@ -0,0 +1,126 @@
+From 632130f0ad0f825bb2faeea997018258a4510fb2 Mon Sep 17 00:00:00 2001
+From: Claudiu Zissulescu <claziss at synopsys.com>
+Date: Mon, 4 Jul 2016 11:11:50 +0200
+Subject: [PATCH 37/89] [ARC] Refurbish mul64 support.
+
+gcc/
+2016-07-04  Claudiu Zissulescu  <claziss at synopsys.com>
+
+	* config/arc/arc.md (mulsidi_600): Changed.
+	(umulsidi_600): Likewise.
+	(mul64): New pattern.
+	(mulu64): Likewise.
+	(mulsidi3): Changed.
+	(umulsidi3): Likewise.
+---
+ gcc/config/arc/arc.md | 64 ++++++++++++++++++++++++++++++++-------------------
+ 1 file changed, 40 insertions(+), 24 deletions(-)
+
+diff --git a/gcc/config/arc/arc.md b/gcc/config/arc/arc.md
+index f9080fb1eb48..cfa55dac5423 100644
+--- a/gcc/config/arc/arc.md
++++ b/gcc/config/arc/arc.md
+@@ -12,10 +12,6 @@
+ ;;    Profiling support and performance improvements by
+ ;;    Joern Rennecke (joern.rennecke at embecosm.com)
+ ;;
+-;;    Support for DSP multiply instructions and mul64
+-;;    instructions for ARC600; and improvements in flag setting
+-;;    instructions by
+-;;    Muhammad Khurram Riaz (Khurram.Riaz at arc.com)
+ 
+ ;; This file is part of GCC.
+ 
+@@ -2011,14 +2007,26 @@
+   [(set_attr "is_sfunc" "yes")
+    (set_attr "predicable" "yes")])
+ 
+-(define_insn "mulsidi_600"
++(define_insn_and_split "mulsidi_600"
++  [(set (match_operand:DI 0 "register_operand"                               "=c, c,c,  c")
++	(mult:DI (sign_extend:DI (match_operand:SI 1 "register_operand"  "%Rcq#q, c,c,  c"))
++		 (sign_extend:DI (match_operand:SI 2 "nonmemory_operand"  "Rcq#q,cL,L,C32"))))
++   (clobber (reg:DI MUL64_OUT_REG))]
++  "TARGET_MUL64_SET"
++  "#"
++  "TARGET_MUL64_SET"
++  [(const_int 0)]
++  "emit_insn (gen_mul64 (operands[1], operands[2]));
++   emit_move_insn (operands[0], gen_rtx_REG (DImode, MUL64_OUT_REG));
++   DONE;"
++  [(set_attr "type" "multi")
++   (set_attr "length" "8")])
++
++(define_insn "mul64"
+   [(set (reg:DI MUL64_OUT_REG)
+-	(mult:DI (sign_extend:DI
+-		   (match_operand:SI 0 "register_operand"  "%Rcq#q,c,c,c"))
+-		 (sign_extend:DI
+-; assembler issue for "I", see mulsi_600
+-;		   (match_operand:SI 1 "register_operand" "Rcq#q,cL,I,Cal"))))]
+-		   (match_operand:SI 1 "register_operand" "Rcq#q,cL,L,C32"))))]
++	(mult:DI
++	 (sign_extend:DI (match_operand:SI 0 "register_operand" "%Rcq#q, c,c,  c"))
++	 (sign_extend:DI (match_operand:SI 1 "nonmemory_operand" "Rcq#q,cL,L,C32"))))]
+   "TARGET_MUL64_SET"
+   "mul64%? \t0, %0, %1%&"
+   [(set_attr "length" "*,4,4,8")
+@@ -2027,14 +2035,26 @@
+    (set_attr "predicable" "yes,yes,no,yes")
+    (set_attr "cond" "canuse,canuse,canuse_limm,canuse")])
+ 
+-(define_insn "umulsidi_600"
++(define_insn_and_split "umulsidi_600"
++  [(set (match_operand:DI 0 "register_operand"                            "=c,c, c")
++	(mult:DI (zero_extend:DI (match_operand:SI 1 "register_operand"   "%c,c, c"))
++		 (sign_extend:DI (match_operand:SI 2 "nonmemory_operand"  "cL,L,C32"))))
++   (clobber (reg:DI MUL64_OUT_REG))]
++  "TARGET_MUL64_SET"
++  "#"
++  "TARGET_MUL64_SET"
++  [(const_int 0)]
++  "emit_insn (gen_mulu64 (operands[1], operands[2]));
++   emit_move_insn (operands[0], gen_rtx_REG (DImode, MUL64_OUT_REG));
++   DONE;"
++  [(set_attr "type" "umulti")
++   (set_attr "length" "8")])
++
++(define_insn "mulu64"
+   [(set (reg:DI MUL64_OUT_REG)
+-	(mult:DI (zero_extend:DI
+-		   (match_operand:SI 0 "register_operand"  "%c,c,c"))
+-		 (sign_extend:DI
+-; assembler issue for "I", see mulsi_600
+-;		   (match_operand:SI 1 "register_operand" "cL,I,Cal"))))]
+-		   (match_operand:SI 1 "register_operand" "cL,L,C32"))))]
++	(mult:DI
++	 (zero_extend:DI (match_operand:SI 0 "register_operand"  "%c,c,c"))
++	 (zero_extend:DI (match_operand:SI 1 "nonmemory_operand" "cL,L,C32"))))]
+   "TARGET_MUL64_SET"
+   "mulu64%? \t0, %0, %1%&"
+   [(set_attr "length" "4,4,8")
+@@ -2098,9 +2118,7 @@
+     }
+   else if (TARGET_MUL64_SET)
+     {
+-      operands[2] = force_reg (SImode, operands[2]);
+-      emit_insn (gen_mulsidi_600 (operands[1], operands[2]));
+-      emit_move_insn (operands[0], gen_rtx_REG (DImode, MUL64_OUT_REG));
++      emit_insn (gen_mulsidi_600 (operands[0], operands[1], operands[2]));
+       DONE;
+     }
+   else if (TARGET_MULMAC_32BY16_SET)
+@@ -2332,9 +2350,7 @@
+     }
+   else if (TARGET_MUL64_SET)
+     {
+-      operands[2] = force_reg (SImode, operands[2]);
+-      emit_insn (gen_umulsidi_600 (operands[1], operands[2]));
+-      emit_move_insn (operands[0], gen_rtx_REG (DImode, MUL64_OUT_REG));
++      emit_insn (gen_umulsidi_600 (operands[0], operands[1], operands[2]));
+       DONE;
+     }
+   else if (TARGET_MULMAC_32BY16_SET)
+-- 
+2.7.4
+
diff --git a/toolchain/gcc/patches/6.3.0/0038-ARC-Fix-PIE.patch b/toolchain/gcc/patches/6.3.0/0038-ARC-Fix-PIE.patch
new file mode 100644
index 0000000..72c757d
--- /dev/null
+++ b/toolchain/gcc/patches/6.3.0/0038-ARC-Fix-PIE.patch
@@ -0,0 +1,100 @@
+From 71d9c8f986cf522d4088f98203084911f79da2fd Mon Sep 17 00:00:00 2001
+From: Claudiu Zissulescu <claziss at synopsys.com>
+Date: Wed, 27 Jul 2016 15:43:33 +0200
+Subject: [PATCH 38/89] [ARC] Fix PIE.
+
+gcc/
+2016-07-27  Cupertino Miranda  <cmiranda at synopsys.com>
+
+	* config/arc/arc.h (STARTFILE_SPEC): Use default linux specs.
+	(ENDFILE_SPEC): Likewise.
+
+libgcc/
+2016-07-27  Cupertino Miranda  <cmiranda at synopsys.com>
+
+	* config.host (arc*-*-linux-uclibc*): Use default extra
+	objects. Include linux-android header.
+	* config/arc/crti.S (_init): Declare symbol as function.
+	(_fini): Likewise.
+---
+ gcc/config.gcc           |  2 +-
+ gcc/config/arc/arc.h     | 10 ++++------
+ libgcc/config.host       |  4 ++--
+ libgcc/config/arc/crti.S |  2 ++
+ 4 files changed, 9 insertions(+), 9 deletions(-)
+
+diff --git a/gcc/config.gcc b/gcc/config.gcc
+index fbf77d3e6347..7b6138aec6bf 100644
+--- a/gcc/config.gcc
++++ b/gcc/config.gcc
+@@ -1025,7 +1025,7 @@ arc*-*-elf*)
+ 	;;
+ arc*-*-linux-uclibc*)
+ 	extra_headers="arc-simd.h"
+-	tm_file="arc/arc-arch.h dbxelf.h elfos.h gnu-user.h linux.h glibc-stdint.h ${tm_file}"
++	tm_file="arc/arc-arch.h dbxelf.h elfos.h gnu-user.h linux.h linux-android.h glibc-stdint.h ${tm_file}"
+ 	tmake_file="${tmake_file} arc/t-uClibc arc/t-arc"
+ 	tm_defines="${tm_defines} TARGET_SDATA_DEFAULT=0"
+ 	tm_defines="${tm_defines} TARGET_MMEDIUM_CALLS_DEFAULT=1"
+diff --git a/gcc/config/arc/arc.h b/gcc/config/arc/arc.h
+index 6a579eba014c..d4cc20ddf708 100644
+--- a/gcc/config/arc/arc.h
++++ b/gcc/config/arc/arc.h
+@@ -138,17 +138,15 @@ extern const char *arc_cpu_to_as (int argc, const char **argv);
+ #define STARTFILE_SPEC "%{!shared:crt0.o%s} crti%O%s %{pg|p:crtg.o%s} " \
+   "%(arc_tls_extra_start_spec) crtbegin.o%s"
+ #else
+-#define STARTFILE_SPEC   "%{!shared:%{!mkernel:crt1.o%s}} crti.o%s \
+-  %{!shared:%{pg|p|profile:crtg.o%s} crtbegin.o%s} %{shared:crtbeginS.o%s}"
+-
++#define STARTFILE_SPEC							\
++  LINUX_OR_ANDROID_LD (GNU_USER_TARGET_STARTFILE_SPEC, ANDROID_STARTFILE_SPEC)
+ #endif
+ 
+ #if DEFAULT_LIBC != LIBC_UCLIBC
+ #define ENDFILE_SPEC "%{pg|p:crtgend.o%s} crtend.o%s crtn%O%s"
+ #else
+-#define ENDFILE_SPEC "%{!shared:%{pg|p|profile:crtgend.o%s} crtend.o%s} \
+-  %{shared:crtendS.o%s} crtn.o%s"
+-
++#define ENDFILE_SPEC							\
++  LINUX_OR_ANDROID_LD (GNU_USER_TARGET_ENDFILE_SPEC, ANDROID_ENDFILE_SPEC)
+ #endif
+ 
+ #if DEFAULT_LIBC == LIBC_UCLIBC
+diff --git a/libgcc/config.host b/libgcc/config.host
+index 4e02765fce74..5102eee42931 100644
+--- a/libgcc/config.host
++++ b/libgcc/config.host
+@@ -371,8 +371,8 @@ arc*-*-elf*)
+ 	;;
+ arc*-*-linux-uclibc*)
+ 	tmake_file="${tmake_file} t-slibgcc-libgcc t-slibgcc-nolc-override arc/t-arc700-uClibc arc/t-arc"
+-	extra_parts="crti.o crtn.o crtend.o crtbegin.o crtendS.o crtbeginS.o libgmon.a crtg.o crtgend.o"
+-	extra_parts="${extra_parts} crttls.o"
++	extra_parts="$extra_parts crti.o crtn.o libgmon.a crtg.o crtgend.o"
++	extra_parts="$extra_parts crttls.o"
+ 	;;
+ arm-wrs-vxworks)
+ 	tmake_file="$tmake_file arm/t-arm arm/t-elf t-softfp-sfdf t-softfp-excl arm/t-softfp t-softfp"
+diff --git a/libgcc/config/arc/crti.S b/libgcc/config/arc/crti.S
+index 7f643056c964..6867ca99e839 100644
+--- a/libgcc/config/arc/crti.S
++++ b/libgcc/config/arc/crti.S
+@@ -31,11 +31,13 @@ see the files COPYING3 and COPYING.RUNTIME respectively.  If not, see
+ 	.section .init
+ 	.global _init
+ 	.word 0
++	.type	_init, at function
+ _init:
+ 	push_s	blink
+ 
+ 	.section .fini
+ 	.global _fini
+ 	.word 0
++	.type	_fini, at function
+ _fini:
+ 	push_s	blink
+-- 
+2.7.4
+
diff --git a/toolchain/gcc/patches/6.3.0/0039-ARC-Generating-code-for-profiling.patch b/toolchain/gcc/patches/6.3.0/0039-ARC-Generating-code-for-profiling.patch
new file mode 100644
index 0000000..70b254b
--- /dev/null
+++ b/toolchain/gcc/patches/6.3.0/0039-ARC-Generating-code-for-profiling.patch
@@ -0,0 +1,2136 @@
+From 9351fca2ef0932f9877c93a74de9cbabcc1aaed4 Mon Sep 17 00:00:00 2001
+From: Claudiu Zissulescu <claziss at synopsys.com>
+Date: Thu, 28 Jul 2016 11:13:00 +0200
+Subject: [PATCH 39/89] [ARC] Generating code for profiling.
+
+gcc/
+2016-07-28  Claudiu Zissulescu  <claziss at synopsys.com>
+
+	* config/arc/arc.h (LINK_SPEC): Tidy up.
+	(ENDFILE_SPEC): Likewise.
+	(LIB_SPEC): Likewise.
+	(STARTFILE_SPEC): Include gcrt0 when profiling.
+	(FUNCTION_PROFILER): Use __mcount.
+	* config/arc/arc.opt (mucb-mcount): Remove.
+	* doc/invoke.texi (ARC): Remove mucb-mcount doc.
+	* arc/arc-protos.h (arc_profile_call): Remove.
+	* arc/arc.c (write_profile_sections): Likewise.
+	(arc_profile_call): Likewise.
+	(unspec_prof_hash): Likewise.
+	(unspec_prof_htab_eq): Likewise.
+	(arc_legitimate_constant_p): Remove UNSPEC_PROF.
+	(arc_reorg): Remove call to write_profile_sections.
+	* arc/arc.md (call): Remove call to arc_profile_call.
+	(call_value): Likewise.
+	(sibcall): Likewise.
+	(sibcall_value): Likewise.
+	(define_constants): Remove UNSPEC_PROF.
+
+libgcc/
+2016-07-28  Claudiu Zissulescu  <claziss at synopsys.com>
+
+	* config.host (arc*-*-linux-uclibc*): Remove libgmon, crtg, and
+	crtgend.
+	(arc*-*-elf*): Likewise.
+	* config/arc/t-arc: Remove old gmon lib targets.
+	* arc/crtg.S: Reomve.
+	* arc/crtgend.S: Likewise.
+	* arc/gmon/atomic.h: Likewise.
+	* arc/gmon/auxreg.h: Likewise.
+	* arc/gmon/dcache_linesz.S: Likewise.
+	* arc/gmon/gmon.c: Likewise.
+	* arc/gmon/machine-gmon.h: Likewise.
+	* arc/gmon/mcount.c: Likewise.
+	* arc/gmon/prof-freq-stub.S: Likewise.
+	* arc/gmon/prof-freq.c: Likewise.
+	* arc/gmon/profil.S: Likewise.
+	* arc/gmon/sys/gmon.h: Likewise.
+	* arc/gmon/sys/gmon_out.h: Likewise.
+	* arc/t-arc-newlib: Likewise.
+        * arc/t-arc700-uClibc: Renamed to t-arc-uClibc.
+---
+ gcc/config/arc/arc-protos.h                        |   1 -
+ gcc/config/arc/arc.c                               | 152 -------
+ gcc/config/arc/arc.h                               |  28 +-
+ gcc/config/arc/arc.md                              |  35 +-
+ gcc/config/arc/arc.opt                             |   4 -
+ gcc/doc/invoke.texi                                |   8 +-
+ libgcc/config.host                                 |  10 +-
+ libgcc/config/arc/crtg.S                           |  51 ---
+ libgcc/config/arc/crtgend.S                        |  33 --
+ libgcc/config/arc/gmon/atomic.h                    |  26 --
+ libgcc/config/arc/gmon/auxreg.h                    |  35 --
+ libgcc/config/arc/gmon/dcache_linesz.S             |  57 ---
+ libgcc/config/arc/gmon/gmon.c                      | 450 ---------------------
+ libgcc/config/arc/gmon/machine-gmon.h              |  65 ---
+ libgcc/config/arc/gmon/mcount.c                    | 206 ----------
+ libgcc/config/arc/gmon/prof-freq-stub.S            |  40 --
+ libgcc/config/arc/gmon/prof-freq.c                 |  60 ---
+ libgcc/config/arc/gmon/profil.S                    | 164 --------
+ libgcc/config/arc/gmon/sys/gmon.h                  | 217 ----------
+ libgcc/config/arc/gmon/sys/gmon_out.h              |  55 ---
+ libgcc/config/arc/t-arc                            |  37 --
+ libgcc/config/arc/t-arc-newlib                     |  22 -
+ .../config/arc/{t-arc700-uClibc => t-arc-uClibc}   |   2 -
+ 23 files changed, 22 insertions(+), 1736 deletions(-)
+ delete mode 100644 libgcc/config/arc/crtg.S
+ delete mode 100644 libgcc/config/arc/crtgend.S
+ delete mode 100644 libgcc/config/arc/gmon/atomic.h
+ delete mode 100644 libgcc/config/arc/gmon/auxreg.h
+ delete mode 100644 libgcc/config/arc/gmon/dcache_linesz.S
+ delete mode 100644 libgcc/config/arc/gmon/gmon.c
+ delete mode 100644 libgcc/config/arc/gmon/machine-gmon.h
+ delete mode 100644 libgcc/config/arc/gmon/mcount.c
+ delete mode 100644 libgcc/config/arc/gmon/prof-freq-stub.S
+ delete mode 100644 libgcc/config/arc/gmon/prof-freq.c
+ delete mode 100644 libgcc/config/arc/gmon/profil.S
+ delete mode 100644 libgcc/config/arc/gmon/sys/gmon.h
+ delete mode 100644 libgcc/config/arc/gmon/sys/gmon_out.h
+ delete mode 100644 libgcc/config/arc/t-arc-newlib
+ rename libgcc/config/arc/{t-arc700-uClibc => t-arc-uClibc} (98%)
+
+diff --git a/gcc/config/arc/arc-protos.h b/gcc/config/arc/arc-protos.h
+index ffc715f2e82a..2c11f3557bf2 100644
+--- a/gcc/config/arc/arc-protos.h
++++ b/gcc/config/arc/arc-protos.h
+@@ -68,7 +68,6 @@ extern bool arc_raw_symbolic_reference_mentioned_p (rtx, bool);
+ extern bool arc_legitimate_pic_operand_p (rtx);
+ extern bool arc_is_longcall_p (rtx);
+ extern bool arc_is_shortcall_p (rtx);
+-extern bool arc_profile_call (rtx callee);
+ extern bool valid_brcc_with_delay_p (rtx *);
+ extern bool small_data_pattern (rtx , machine_mode);
+ extern rtx arc_rewrite_small_data (rtx);
+diff --git a/gcc/config/arc/arc.c b/gcc/config/arc/arc.c
+index b0b21ad8b59f..4e478131da35 100644
+--- a/gcc/config/arc/arc.c
++++ b/gcc/config/arc/arc.c
+@@ -3733,97 +3733,6 @@ arc_print_operand_address (FILE *file , rtx addr)
+     }
+ }
+ 
+-/* Called via walk_stores.  DATA points to a hash table we can use to
+-   establish a unique SYMBOL_REF for each counter, which corresponds to
+-   a caller-callee pair.
+-   X is a store which we want to examine for an UNSPEC_PROF, which
+-   would be an address loaded into a register, or directly used in a MEM.
+-   If we found an UNSPEC_PROF, if we encounter a new counter the first time,
+-   write out a description and a data allocation for a 32 bit counter.
+-   Also, fill in the appropriate symbol_ref into each UNSPEC_PROF instance.  */
+-
+-static void
+-write_profile_sections (rtx dest ATTRIBUTE_UNUSED, rtx x, void *data)
+-{
+-  rtx *srcp, src;
+-  htab_t htab = (htab_t) data;
+-  rtx *slot;
+-
+-  if (GET_CODE (x) != SET)
+-    return;
+-  srcp = &SET_SRC (x);
+-  if (MEM_P (*srcp))
+-    srcp = &XEXP (*srcp, 0);
+-  else if (MEM_P (SET_DEST (x)))
+-    srcp = &XEXP (SET_DEST (x), 0);
+-  src = *srcp;
+-  if (GET_CODE (src) != CONST)
+-    return;
+-  src = XEXP (src, 0);
+-  if (GET_CODE (src) != UNSPEC || XINT (src, 1) != UNSPEC_PROF)
+-    return;
+-
+-  gcc_assert (XVECLEN (src, 0) == 3);
+-  if (!htab_elements (htab))
+-    {
+-      output_asm_insn (".section .__arc_profile_desc, \"a\"\n"
+-		       "\t.long %0 + 1\n",
+-		       &XVECEXP (src, 0, 0));
+-    }
+-  slot = (rtx *) htab_find_slot (htab, src, INSERT);
+-  if (*slot == HTAB_EMPTY_ENTRY)
+-    {
+-      static int count_nr;
+-      char buf[24];
+-      rtx count;
+-
+-      *slot = src;
+-      sprintf (buf, "__prof_count%d", count_nr++);
+-      count = gen_rtx_SYMBOL_REF (Pmode, xstrdup (buf));
+-      XVECEXP (src, 0, 2) = count;
+-      output_asm_insn (".section\t.__arc_profile_desc, \"a\"\n"
+-		       "\t.long\t%1\n"
+-		       "\t.section\t.__arc_profile_counters, \"aw\"\n"
+-		       "\t.type\t%o2, @object\n"
+-		       "\t.size\t%o2, 4\n"
+-		       "%o2:\t.zero 4",
+-		       &XVECEXP (src, 0, 0));
+-      *srcp = count;
+-    }
+-  else
+-    *srcp = XVECEXP (*slot, 0, 2);
+-}
+-
+-/* Hash function for UNSPEC_PROF htab.  Use both the caller's name and
+-   the callee's name (if known).  */
+-
+-static hashval_t
+-unspec_prof_hash (const void *x)
+-{
+-  const_rtx u = (const_rtx) x;
+-  const_rtx s1 = XVECEXP (u, 0, 1);
+-
+-  return (htab_hash_string (XSTR (XVECEXP (u, 0, 0), 0))
+-	  ^ (s1->code == SYMBOL_REF ? htab_hash_string (XSTR (s1, 0)) : 0));
+-}
+-
+-/* Equality function for UNSPEC_PROF htab.  Two pieces of UNSPEC_PROF rtl
+-   shall refer to the same counter if both caller name and callee rtl
+-   are identical.  */
+-
+-static int
+-unspec_prof_htab_eq (const void *x, const void *y)
+-{
+-  const_rtx u0 = (const_rtx) x;
+-  const_rtx u1 = (const_rtx) y;
+-  const_rtx s01 = XVECEXP (u0, 0, 1);
+-  const_rtx s11 = XVECEXP (u1, 0, 1);
+-
+-  return (!strcmp (XSTR (XVECEXP (u0, 0, 0), 0),
+-		   XSTR (XVECEXP (u1, 0, 0), 0))
+-	  && rtx_equal_p (s01, s11));
+-}
+-
+ /* Conditional execution support.
+ 
+    This is based on the ARM port but for now is much simpler.
+@@ -5563,7 +5472,6 @@ arc_legitimate_constant_p (machine_mode mode, rtx x)
+ 	  case UNSPEC_TLS_GD:
+ 	  case UNSPEC_TLS_IE:
+ 	  case UNSPEC_TLS_OFF:
+-	  case UNSPEC_PROF:
+ 	    return true;
+ 
+ 	  default:
+@@ -6483,47 +6391,6 @@ arc_is_shortcall_p (rtx sym_ref)
+ 
+ }
+ 
+-/* Emit profiling code for calling CALLEE.  Return true if a special
+-   call pattern needs to be generated.  */
+-
+-bool
+-arc_profile_call (rtx callee)
+-{
+-  rtx from = XEXP (DECL_RTL (current_function_decl), 0);
+-
+-  if (TARGET_UCB_MCOUNT)
+-    /* Profiling is done by instrumenting the callee.  */
+-    return false;
+-
+-  if (CONSTANT_P (callee))
+-    {
+-      rtx count_ptr
+-	= gen_rtx_CONST (Pmode,
+-			 gen_rtx_UNSPEC (Pmode,
+-					 gen_rtvec (3, from, callee,
+-						    CONST0_RTX (Pmode)),
+-					 UNSPEC_PROF));
+-      rtx counter = gen_rtx_MEM (SImode, count_ptr);
+-      /* ??? The increment would better be done atomically, but as there is
+-	 no proper hardware support, that would be too expensive.  */
+-      emit_move_insn (counter,
+-		      force_reg (SImode, plus_constant (SImode, counter, 1)));
+-      return false;
+-    }
+-  else
+-    {
+-      rtx count_list_ptr
+-	= gen_rtx_CONST (Pmode,
+-			 gen_rtx_UNSPEC (Pmode,
+-					 gen_rtvec (3, from, CONST0_RTX (Pmode),
+-						    CONST0_RTX (Pmode)),
+-					 UNSPEC_PROF));
+-      emit_move_insn (gen_rtx_REG (Pmode, 8), count_list_ptr);
+-      emit_move_insn (gen_rtx_REG (Pmode, 9), callee);
+-      return true;
+-    }
+-}
+-
+ /* Worker function for TARGET_RETURN_IN_MEMORY.  */
+ 
+ static bool
+@@ -6670,25 +6537,6 @@ arc_reorg (void)
+   cfun->machine->arc_reorg_started = 1;
+   arc_reorg_in_progress = 1;
+ 
+-  /* Emit special sections for profiling.  */
+-  if (crtl->profile)
+-    {
+-      section *save_text_section;
+-      rtx_insn *insn;
+-      int size = get_max_uid () >> 4;
+-      htab_t htab = htab_create (size, unspec_prof_hash, unspec_prof_htab_eq,
+-				 NULL);
+-
+-      save_text_section = in_section;
+-      for (insn = get_insns (); insn; insn = NEXT_INSN (insn))
+-	if (NONJUMP_INSN_P (insn))
+-	  walk_stores (PATTERN (insn), write_profile_sections, htab);
+-      if (htab_elements (htab))
+-	in_section = 0;
+-      switch_to_section (save_text_section);
+-      htab_delete (htab);
+-    }
+-
+   /* Link up loop ends with their loop start.  */
+   {
+     for (insn = get_insns (); insn; insn = NEXT_INSN (insn))
+diff --git a/gcc/config/arc/arc.h b/gcc/config/arc/arc.h
+index d4cc20ddf708..3df21d416d97 100644
+--- a/gcc/config/arc/arc.h
++++ b/gcc/config/arc/arc.h
+@@ -121,12 +121,11 @@ extern const char *arc_cpu_to_as (int argc, const char **argv);
+ 		   -X %{mbig-endian:-EB} \
+ 		   %{EB} %{EL} \
+ 		   %{marclinux*} \
+-		   %{!marclinux*: %{pg|p|profile:-marclinux_prof;: -marclinux}} \
++		   %{!marclinux*: -marclinux} \
+ 		   %{!z:-z max-page-size=0x2000 -z common-page-size=0x2000} \
+ 		   %{shared:-shared}"
+ #else
+-#define LINK_SPEC "%{mbig-endian:-EB} %{EB} %{EL}\
+-  %{pg|p:-marcelf_prof;mA7|mARC700|mcpu=arc700|mcpu=ARC700: -marcelf}"
++#define LINK_SPEC "%{mbig-endian:-EB} %{EB} %{EL}"
+ #endif
+ 
+ #if DEFAULT_LIBC != LIBC_UCLIBC
+@@ -135,7 +134,7 @@ extern const char *arc_cpu_to_as (int argc, const char **argv);
+ #define EXTRA_SPECS \
+   { "arc_tls_extra_start_spec", ARC_TLS_EXTRA_START_SPEC }, \
+ 
+-#define STARTFILE_SPEC "%{!shared:crt0.o%s} crti%O%s %{pg|p:crtg.o%s} " \
++#define STARTFILE_SPEC "%{pg|p:gcrt0.o%s}%{!pg:%{!p:crt0.o%s}} crti%O%s " \
+   "%(arc_tls_extra_start_spec) crtbegin.o%s"
+ #else
+ #define STARTFILE_SPEC							\
+@@ -143,7 +142,7 @@ extern const char *arc_cpu_to_as (int argc, const char **argv);
+ #endif
+ 
+ #if DEFAULT_LIBC != LIBC_UCLIBC
+-#define ENDFILE_SPEC "%{pg|p:crtgend.o%s} crtend.o%s crtn%O%s"
++#define ENDFILE_SPEC "crtend.o%s crtn%O%s"
+ #else
+ #define ENDFILE_SPEC							\
+   LINUX_OR_ANDROID_LD (GNU_USER_TARGET_ENDFILE_SPEC, ANDROID_ENDFILE_SPEC)
+@@ -154,12 +153,11 @@ extern const char *arc_cpu_to_as (int argc, const char **argv);
+ #define LIB_SPEC  \
+   "%{pthread:-lpthread} \
+    %{shared:-lc} \
+-   %{!shared:%{pg|p|profile:-lgmon -u profil --defsym __profil=profil} -lc}"
++   %{!shared:%{profile:-lc_p}%{!profile:-lc}}"
+ #define TARGET_ASM_FILE_END file_end_indicate_exec_stack
+ #else
+ #undef LIB_SPEC
+-/* -lc_p not present for arc-elf32-* : ashwin */
+-#define LIB_SPEC "%{!shared:%{g*:-lg} %{pg|p:-lgmon} -lc}"
++#define LIB_SPEC "%{!shared:%{g*:-lg} -lc}"
+ #endif
+ 
+ #ifndef DRIVER_ENDIAN_SELF_SPECS
+@@ -918,12 +916,14 @@ extern int arc_initial_elimination_offset(int from, int to);
+   (OFFSET) = arc_initial_elimination_offset ((FROM), (TO))
+ 
+ /* Output assembler code to FILE to increment profiler label # LABELNO
+-   for profiling a function entry.
+-   We actually emit the profiler code at the call site, so leave this one
+-   empty.  */
+-#define FUNCTION_PROFILER(FILE, LABELNO) \
+-  if (TARGET_UCB_MCOUNT) \
+-    fprintf (FILE, "\t%s\n", arc_output_libcall ("__mcount"))
++   for profiling a function entry.  */
++#define FUNCTION_PROFILER(FILE, LABELNO)			\
++  do {								\
++  if (flag_pic)							\
++    fprintf (FILE, "\tbl\t__mcount at plt\n");			\
++  else								\
++    fprintf (FILE, "\tbl\t__mcount\n");				\
++  } while (0);
+ 
+ #define NO_PROFILE_COUNTERS  1
+ 
+diff --git a/gcc/config/arc/arc.md b/gcc/config/arc/arc.md
+index cfa55dac5423..d87174a7f321 100644
+--- a/gcc/config/arc/arc.md
++++ b/gcc/config/arc/arc.md
+@@ -9,7 +9,7 @@
+ ;;    Saurabh Verma (saurabh.verma at codito.com)
+ ;;    Ramana Radhakrishnan(ramana.radhakrishnan at codito.com)
+ ;;
+-;;    Profiling support and performance improvements by
++;;    Performance improvements by
+ ;;    Joern Rennecke (joern.rennecke at embecosm.com)
+ ;;
+ 
+@@ -165,9 +165,7 @@
+   ])
+ 
+ (define_constants
+-  [(UNSPEC_PROF 18) ; profile callgraph counter
+-
+-   (R0_REG 0)
++  [(R0_REG 0)
+    (R1_REG 1)
+    (R2_REG 2)
+    (R3_REG 3)
+@@ -4063,13 +4061,6 @@
+ 
+     gcc_assert (MEM_P (operands[0]));
+     callee  = XEXP (operands[0], 0);
+-    if (crtl->profile && arc_profile_call (callee))
+-      {
+-	emit_call_insn (gen_call_prof (gen_rtx_SYMBOL_REF (Pmode,
+-							   \"_mcount_call\"),
+-				       operands[1]));
+-	DONE;
+-      }
+     /* This is to decide if we should generate indirect calls by loading the
+        32 bit address of the callee into a register before performing the
+        branch and link - this exposes cse opportunities.
+@@ -4132,14 +4123,6 @@
+ 
+     gcc_assert (MEM_P (operands[1]));
+     callee = XEXP (operands[1], 0);
+-    if (crtl->profile && arc_profile_call (callee))
+-      {
+-	emit_call_insn (gen_call_value_prof (operands[0],
+-					     gen_rtx_SYMBOL_REF (Pmode,
+-							    \"_mcount_call\"),
+-					     operands[2]));
+-	DONE;
+-      }
+      /* See the comment in define_expand \"call\".  */
+     if (GET_CODE (callee) != REG
+ 	&& (GET_CODE (callee) == PLUS || arc_is_longcall_p (callee)))
+@@ -4622,13 +4605,6 @@
+ 
+     if (operands[2] == NULL_RTX)
+       operands[2] = const0_rtx;
+-    if (crtl->profile && arc_profile_call (callee))
+-      {
+-	emit_insn (gen_sibcall_prof
+-		    (gen_rtx_SYMBOL_REF (Pmode, \"_mcount_call\"),
+-		     operands[1], operands[2]));
+-	DONE;
+-      }
+     if (GET_CODE (callee) != REG
+ 	&& (GET_CODE (callee) == PLUS || arc_is_longcall_p (callee)))
+       XEXP (operands[0], 0) = force_reg (Pmode, callee);
+@@ -4648,13 +4624,6 @@
+ 
+     if (operands[3] == NULL_RTX)
+       operands[3] = const0_rtx;
+-    if (crtl->profile && arc_profile_call (XEXP (operands[1], 0)))
+-      {
+-	emit_insn (gen_sibcall_value_prof
+-		    (operands[0], gen_rtx_SYMBOL_REF (Pmode, \"_mcount_call\"),
+-		     operands[2], operands[3]));
+-	DONE;
+-      }
+     if (GET_CODE (callee) != REG && arc_is_longcall_p (callee))
+       XEXP (operands[1], 0) = force_reg (Pmode, callee);
+   }"
+diff --git a/gcc/config/arc/arc.opt b/gcc/config/arc/arc.opt
+index 15785498b34e..d8b26102d469 100644
+--- a/gcc/config/arc/arc.opt
++++ b/gcc/config/arc/arc.opt
+@@ -346,10 +346,6 @@ mlra-priority-noncompact
+ Target RejectNegative Var(arc_lra_prioritytag, ARC_LRA_PRIORITY_NONCOMPACT)
+ Reduce priority for r0..r3 / r12..r15 with TARGET_REGISTER_PRIORITY.
+ 
+-mucb-mcount
+-Target Report Var(TARGET_UCB_MCOUNT)
+-instrument with mcount calls as in the ucb code.
+-
+ ; backward-compatibility aliases, translated by DRIVER_SELF_SPECS
+ 
+ mEA
+diff --git a/gcc/doc/invoke.texi b/gcc/doc/invoke.texi
+index a3fa950d064b..c4d574660c1a 100644
+--- a/gcc/doc/invoke.texi
++++ b/gcc/doc/invoke.texi
+@@ -592,7 +592,7 @@ Objective-C and Objective-C++ Dialects}.
+ -mcrc -mdsp-packa -mdvbf -mlock -mmac-d16 -mmac-24 -mrtsc -mswape @gol
+ -mtelephony -mxy -misize -mannotate-align -marclinux -marclinux_prof @gol
+ -mlong-calls -mmedium-calls -msdata @gol
+--mucb-mcount -mvolatile-cache -mtp-regno=@var{regno} @gol
++-mvolatile-cache -mtp-regno=@var{regno} @gol
+ -malign-call -mauto-modify-reg -mbbit-peephole -mno-brcc @gol
+ -mcase-vector-pcrel -mcompact-casesi -mno-cond-exec -mearly-cbranchsi @gol
+ -mexpand-adddi -mindexed-loads -mlra -mlra-priority-none @gol
+@@ -13658,12 +13658,6 @@ Do not generate sdata references.  This is the default for tool chains
+ built for @w{@code{arc-linux-uclibc}} and @w{@code{arceb-linux-uclibc}}
+ targets.
+ 
+- at item -mucb-mcount
+- at opindex mucb-mcount
+-Instrument with mcount calls as used in UCB code.  I.e. do the
+-counting in the callee, not the caller.  By default ARC instrumentation
+-counts in the caller.
+-
+ @item -mvolatile-cache
+ @opindex mvolatile-cache
+ Use ordinarily cached memory accesses for volatile references.  This is the
+diff --git a/libgcc/config.host b/libgcc/config.host
+index 5102eee42931..035d38d03713 100644
+--- a/libgcc/config.host
++++ b/libgcc/config.host
+@@ -365,13 +365,13 @@ alpha*-dec-*vms*)
+ 	md_unwind_header=alpha/vms-unwind.h
+ 	;;
+ arc*-*-elf*)
+-	tmake_file="arc/t-arc-newlib arc/t-arc"
+-	extra_parts="crti.o crtn.o crtend.o crtbegin.o crtendS.o crtbeginS.o libgmon.a crtg.o crtgend.o"
+-	extra_parts="${extra_parts} crttls.o"
++	tmake_file="arc/t-arc"
++	extra_parts="crti.o crtn.o crtend.o crtbegin.o crtendS.o crtbeginS.o"
++	extra_parts="$extra_parts crttls.o"
+ 	;;
+ arc*-*-linux-uclibc*)
+-	tmake_file="${tmake_file} t-slibgcc-libgcc t-slibgcc-nolc-override arc/t-arc700-uClibc arc/t-arc"
+-	extra_parts="$extra_parts crti.o crtn.o libgmon.a crtg.o crtgend.o"
++	tmake_file="${tmake_file} t-slibgcc-libgcc t-slibgcc-nolc-override arc/t-arc-uClibc arc/t-arc"
++	extra_parts="$extra_parts crti.o crtn.o"
+ 	extra_parts="$extra_parts crttls.o"
+ 	;;
+ arm-wrs-vxworks)
+diff --git a/libgcc/config/arc/crtg.S b/libgcc/config/arc/crtg.S
+deleted file mode 100644
+index ca3cfb6a9cbe..000000000000
+--- a/libgcc/config/arc/crtg.S
++++ /dev/null
+@@ -1,51 +0,0 @@
+-/* Code to start and stop profiling for the Synopsys DesignWare ARC CPU.
+-
+-   Copyright (C) 1994-2016 Free Software Foundation, Inc.
+-   Contributor: Joern Rennecke <joern.rennecke at embecosm.com>
+-		on behalf of Synopsys Inc.
+-
+-This file is part of GCC.
+-
+-GCC is free software; you can redistribute it and/or modify it under
+-the terms of the GNU General Public License as published by the Free
+-Software Foundation; either version 3, or (at your option) any later
+-version.
+-
+-GCC is distributed in the hope that it will be useful, but WITHOUT ANY
+-WARRANTY; without even the implied warranty of MERCHANTABILITY or
+-FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+-for more details.
+-
+-Under Section 7 of GPL version 3, you are granted additional
+-permissions described in the GCC Runtime Library Exception, version
+-3.1, as published by the Free Software Foundation.
+-
+-You should have received a copy of the GNU General Public License and
+-a copy of the GCC Runtime Library Exception along with this program;
+-see the files COPYING3 and COPYING.RUNTIME respectively.  If not, see
+-<http://www.gnu.org/licenses/>.  */
+-
+-	.section .init
+-	.global _init
+-	.global _fini
+-	.global __monstartup
+-	mov_s	r0,_init
+-	mov_s	r1,_fini
+-	jl	__monstartup
+-
+-	.section .__arc_profile_desc, "a"
+-	.global __arc_profile_desc_secstart
+-	.balign	4
+-__arc_profile_desc_secstart:
+-	.section .__arc_profile_forward, "a"
+-	.global __arc_profile_forward_secstart
+-	.balign 4
+-__arc_profile_forward_secstart:
+-	.section .__arc_profile_counters, "aw"
+-	.global __arc_profile_counters_secstart
+-	.balign	4
+-__arc_profile_counters_secstart:
+-
+-	.section .fini
+-	.global _mcleanup
+-	jl	_mcleanup
+diff --git a/libgcc/config/arc/crtgend.S b/libgcc/config/arc/crtgend.S
+deleted file mode 100644
+index fad630f139e5..000000000000
+--- a/libgcc/config/arc/crtgend.S
++++ /dev/null
+@@ -1,33 +0,0 @@
+-/* Code to start and stop profiling for the Synopsys DesignWare ARC CPU.
+-
+-   Copyright (C) 1994-2016 Free Software Foundation, Inc.
+-   Contributor: Joern Rennecke <joern.rennecke at embecosm.com>
+-		on behalf of Synopsys Inc.
+-
+-This file is part of GCC.
+-
+-GCC is free software; you can redistribute it and/or modify it under
+-the terms of the GNU General Public License as published by the Free
+-Software Foundation; either version 3, or (at your option) any later
+-version.
+-
+-GCC is distributed in the hope that it will be useful, but WITHOUT ANY
+-WARRANTY; without even the implied warranty of MERCHANTABILITY or
+-FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+-for more details.
+-
+-Under Section 7 of GPL version 3, you are granted additional
+-permissions described in the GCC Runtime Library Exception, version
+-3.1, as published by the Free Software Foundation.
+-
+-You should have received a copy of the GNU General Public License and
+-a copy of the GCC Runtime Library Exception along with this program;
+-see the files COPYING3 and COPYING.RUNTIME respectively.  If not, see
+-<http://www.gnu.org/licenses/>.  */
+-
+-	.section .__arc_profile_desc, "a"
+-	.global __arc_profile_desc_secend
+-__arc_profile_desc_secend:
+-	.section .__arc_profile_forward, "a"
+-	.global __arc_profile_forward_secend
+-__arc_profile_forward_secend:
+diff --git a/libgcc/config/arc/gmon/atomic.h b/libgcc/config/arc/gmon/atomic.h
+deleted file mode 100644
+index 049aa523b5b9..000000000000
+--- a/libgcc/config/arc/gmon/atomic.h
++++ /dev/null
+@@ -1,26 +0,0 @@
+-/* Copyright (C) 2007-2016 Free Software Foundation, Inc.
+-   Contributor: Joern Rennecke <joern.rennecke at embecosm.com>
+-		on behalf of Synopsys Inc.
+-
+-This file is part of GCC.
+-
+-GCC is free software; you can redistribute it and/or modify it under
+-the terms of the GNU General Public License as published by the Free
+-Software Foundation; either version 3, or (at your option) any later
+-version.
+-
+-GCC is distributed in the hope that it will be useful, but WITHOUT ANY
+-WARRANTY; without even the implied warranty of MERCHANTABILITY or
+-FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+-for more details.
+-
+-Under Section 7 of GPL version 3, you are granted additional
+-permissions described in the GCC Runtime Library Exception, version
+-3.1, as published by the Free Software Foundation.
+-
+-You should have received a copy of the GNU General Public License and
+-a copy of the GCC Runtime Library Exception along with this program;
+-see the files COPYING3 and COPYING.RUNTIME respectively.  If not, see
+-<http://www.gnu.org/licenses/>.  */
+-
+-/* File deliberately left blank. */
+diff --git a/libgcc/config/arc/gmon/auxreg.h b/libgcc/config/arc/gmon/auxreg.h
+deleted file mode 100644
+index 5210ea02ccc8..000000000000
+--- a/libgcc/config/arc/gmon/auxreg.h
++++ /dev/null
+@@ -1,35 +0,0 @@
+-/* Copyright (C) 2007-2016 Free Software Foundation, Inc.
+-   Contributor: Joern Rennecke <joern.rennecke at embecosm.com>
+-		on behalf of Synopsys Inc.
+-
+-This file is part of GCC.
+-
+-GCC is free software; you can redistribute it and/or modify it under
+-the terms of the GNU General Public License as published by the Free
+-Software Foundation; either version 3, or (at your option) any later
+-version.
+-
+-GCC is distributed in the hope that it will be useful, but WITHOUT ANY
+-WARRANTY; without even the implied warranty of MERCHANTABILITY or
+-FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+-for more details.
+-
+-Under Section 7 of GPL version 3, you are granted additional
+-permissions described in the GCC Runtime Library Exception, version
+-3.1, as published by the Free Software Foundation.
+-
+-You should have received a copy of the GNU General Public License and
+-a copy of the GCC Runtime Library Exception along with this program;
+-see the files COPYING3 and COPYING.RUNTIME respectively.  If not, see
+-<http://www.gnu.org/licenses/>.  */
+-
+-#define	LP_START	0x02
+-#define	LP_END		0x03
+-#define IDENTITY	0x04
+-#define STATUS32	0x0a
+-#define	COUNT0		0x21 /* Timer 0 count */
+-#define	CONTROL0	0x22 /* Timer 0 control */
+-#define	LIMIT0		0x23 /* Timer 0 limit */
+-#define INT_VECTOR_BASE	0x25
+-#define D_CACHE_BUILD	0x72
+-#define DC_FLDL		0x4c
+diff --git a/libgcc/config/arc/gmon/dcache_linesz.S b/libgcc/config/arc/gmon/dcache_linesz.S
+deleted file mode 100644
+index 29572aefc8e9..000000000000
+--- a/libgcc/config/arc/gmon/dcache_linesz.S
++++ /dev/null
+@@ -1,57 +0,0 @@
+-/* This file contains code to do profiling.
+-
+-   Copyright (C) 2007-2016 Free Software Foundation, Inc.
+-   Contributor: Joern Rennecke <joern.rennecke at embecosm.com>
+-		on behalf of Synopsys Inc.
+-
+-This file is part of GCC.
+-
+-GCC is free software; you can redistribute it and/or modify it under
+-the terms of the GNU General Public License as published by the Free
+-Software Foundation; either version 3, or (at your option) any later
+-version.
+-
+-GCC is distributed in the hope that it will be useful, but WITHOUT ANY
+-WARRANTY; without even the implied warranty of MERCHANTABILITY or
+-FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+-for more details.
+-
+-Under Section 7 of GPL version 3, you are granted additional
+-permissions described in the GCC Runtime Library Exception, version
+-3.1, as published by the Free Software Foundation.
+-
+-You should have received a copy of the GNU General Public License and
+-a copy of the GCC Runtime Library Exception along with this program;
+-see the files COPYING3 and COPYING.RUNTIME respectively.  If not, see
+-<http://www.gnu.org/licenses/>.  */
+-
+-#include "../asm.h"
+-#include "auxreg.h"
+-/*  This file contains code to do profiling.  */
+-	.weak	__profile_timer_cycles
+-	.global __profile_timer_cycles
+-	.set	__profile_timer_cycles, 200
+-	.text
+-	; For Arctangent-A5, if no data cache is present, a read of the
+-	; cache build register returns the ID register.  For ARC600 and
+-	; later, the version field will be zero.
+-	.global	__dcache_linesz
+-	.balign	4
+-__dcache_linesz:
+-#if !defined (__EM__) && !defined (__HS__)
+-	lr	r12,[D_CACHE_BUILD]
+-	extb_s	r0,r12
+-	breq_s	r0,0,.Lsz_nocache
+-	brge	r0,0x20,.Lsz_havecache
+-	lr	r0,[IDENTITY]
+-	breq	r12,r0,.Lsz_nocache
+-.Lsz_havecache:
+-	lsr_s	r12,r12,16
+-	mov_s	r0,16
+-	bmsk_s	r12,r12,3
+-	asl_s	r0,r0,r12
+-	j_s	[blink]
+-.Lsz_nocache:
+-#endif /* !__EM__  && !__HS__ */
+-	mov_s	r0,1
+-	j_s	[blink]
+diff --git a/libgcc/config/arc/gmon/gmon.c b/libgcc/config/arc/gmon/gmon.c
+deleted file mode 100644
+index 82c09b0a1a2d..000000000000
+--- a/libgcc/config/arc/gmon/gmon.c
++++ /dev/null
+@@ -1,450 +0,0 @@
+-/*-
+- * Copyright (c) 1983, 1992, 1993
+- *	The Regents of the University of California.  All rights reserved.
+- * Copyright (C) 2007-2016 Free Software Foundation, Inc.
+- *
+- * Redistribution and use in source and binary forms, with or without
+- * modification, are permitted provided that the following conditions
+- * are met:
+- * 1. Redistributions of source code must retain the above copyright
+- *    notice, this list of conditions and the following disclaimer.
+- * 2. Redistributions in binary form must reproduce the above copyright
+- *    notice, this list of conditions and the following disclaimer in the
+- *    documentation and/or other materials provided with the distribution.
+- * 4. Neither the name of the University nor the names of its contributors
+- *    may be used to endorse or promote products derived from this software
+- *    without specific prior written permission.
+- *
+- * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+- * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+- * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+- * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+- * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+- * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+- * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+- * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+- * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+- * SUCH DAMAGE.
+- */
+-#if 0
+-#include <sys/param.h>
+-#include <sys/time.h>
+-#endif
+-#include <sys/gmon.h>
+-#include <sys/gmon_out.h>
+-
+-#include <stddef.h>
+-#include <errno.h>
+-#include <stdio.h>
+-#include <fcntl.h>
+-#include <unistd.h>
+-
+-#include <stdio.h>
+-#include <stdlib.h>
+-#include <string.h>
+-#include <unistd.h>
+-#if 0
+-#include <libc-internal.h>
+-#include <not-cancel.h>
+-
+-#ifdef USE_IN_LIBIO
+-# include <wchar.h>
+-#endif
+-#endif
+-#define internal_function
+-#define weak_alias(fun,aliasid) extern __typeof(fun) aliasid __attribute__ ((weak, alias (#fun)));
+-#define __libc_enable_secure 0
+-
+-/*  Head of basic-block list or NULL. */
+-struct __bb *__bb_head attribute_hidden;
+-
+-struct gmonparam _gmonparam attribute_hidden = { GMON_PROF_OFF };
+-
+-/*
+- * See profil(2) where this is described:
+- */
+-static int	s_scale;
+-#define		SCALE_1_TO_1	0x10000L
+-
+-#define ERR(s) write (STDERR_FILENO, s, sizeof (s) - 1)
+-
+-void moncontrol (int mode);
+-void __moncontrol (int mode);
+-static void write_hist (int fd) internal_function;
+-static void write_call_graph (int fd) internal_function;
+-static void write_bb_counts (int fd) internal_function;
+-
+-/*
+- * Control profiling
+- *	profiling is what mcount checks to see if
+- *	all the data structures are ready.
+- */
+-void
+-__moncontrol (int mode)
+-{
+-  struct gmonparam *p = &_gmonparam;
+-
+-  /* Don't change the state if we ran into an error.  */
+-  if (p->state == GMON_PROF_ERROR)
+-    return;
+-
+-  if (mode)
+-    {
+-      /* start */
+-      __profil((void *) p->kcount, p->kcountsize, p->lowpc, s_scale);
+-      p->state = GMON_PROF_ON;
+-    }
+-  else
+-    {
+-      /* stop */
+-      __profil(NULL, 0, 0, 0);
+-      p->state = GMON_PROF_OFF;
+-    }
+-}
+-weak_alias (__moncontrol, moncontrol)
+-
+-
+-void
+-__monstartup (u_long lowpc, u_long highpc)
+-{
+-  register int o;
+-  char *cp;
+-  struct gmonparam *p = &_gmonparam;
+-  int linesz;
+-
+-  /*
+-   * round lowpc and highpc to multiples of the density we're using
+-   * so the rest of the scaling (here and in gprof) stays in ints.
+-   */
+-  p->lowpc = ROUNDDOWN(lowpc, HISTFRACTION * sizeof(HISTCOUNTER));
+-  if (sizeof *p->froms % sizeof(HISTCOUNTER) != 0)
+-    {
+-      p->highpc = ROUNDUP(highpc, HISTFRACTION * sizeof(HISTCOUNTER));
+-      p->textsize = p->highpc - p->lowpc;
+-      p->kcountsize = ROUNDUP((p->textsize + HISTFRACTION - 1) / HISTFRACTION,
+-			      sizeof (*p->froms));
+-    }
+-  else
+-    {
+-      /* Avoid odd scales by rounding up highpc to get kcountsize rounded.  */
+-      p->textsize = ROUNDUP (highpc - p->lowpc,
+-			     HISTFRACTION * sizeof (*p->froms));
+-      p->highpc = p->lowpc + p->textsize;
+-      p->kcountsize = p->textsize / HISTFRACTION;
+-    }
+-  p->hashfraction = HASHFRACTION;
+-  p->log_hashfraction = -1;
+-  /* The following test must be kept in sync with the corresponding
+-     test in mcount.c.  */
+-  if ((HASHFRACTION & (HASHFRACTION - 1)) == 0) {
+-      /* if HASHFRACTION is a power of two, mcount can use shifting
+-	 instead of integer division.  Precompute shift amount. */
+-      p->log_hashfraction = ffs(p->hashfraction * sizeof(*p->froms)) - 1;
+-  }
+-  p->tolimit = p->textsize * ARCDENSITY / 100;
+-  if (p->tolimit < MINARCS)
+-    p->tolimit = MINARCS;
+-  else if (p->tolimit > MAXARCS)
+-    p->tolimit = MAXARCS;
+-  p->tossize = p->tolimit * sizeof(struct tostruct);
+-
+-  /* p->kcount must not share cache lines with the adjacent data, because
+-     we use uncached accesses while profiling.  */
+-  linesz = __dcache_linesz ();
+-  cp = calloc (ROUNDUP (p->kcountsize, linesz) + p->tossize
+-	       + (linesz - 1), 1);
+-  if (! cp)
+-    {
+-      ERR("monstartup: out of memory\n");
+-      p->tos = NULL;
+-      p->state = GMON_PROF_ERROR;
+-      /* In case we loose the error state due to a race,
+-	 prevent invalid writes also by clearing tolimit.  */
+-      p->tolimit = 0;
+-      return;
+-    }
+-  p->tos = (struct tostruct *)cp;
+-  cp += p->tossize;
+-  cp = (char *) ROUNDUP ((ptrdiff_t) cp, linesz);
+-  p->kcount = (HISTCOUNTER *)cp;
+-  cp += ROUNDUP (p->kcountsize, linesz);
+-
+-  p->tos[0].link = 0;
+-
+-  o = p->highpc - p->lowpc;
+-  if (p->kcountsize < (u_long) o)
+-    {
+-#ifndef hp300
+-      s_scale = ((float)p->kcountsize / o ) * SCALE_1_TO_1;
+-#else
+-      /* avoid floating point operations */
+-      int quot = o / p->kcountsize;
+-
+-      if (quot >= 0x10000)
+-	s_scale = 1;
+-      else if (quot >= 0x100)
+-	s_scale = 0x10000 / quot;
+-      else if (o >= 0x800000)
+-	s_scale = 0x1000000 / (o / (p->kcountsize >> 8));
+-      else
+-	s_scale = 0x1000000 / ((o << 8) / p->kcountsize);
+-#endif
+-    } else
+-      s_scale = SCALE_1_TO_1;
+-
+-  __moncontrol(1);
+-}
+-weak_alias (__monstartup, monstartup)
+-
+-
+-static void
+-internal_function
+-write_hist (int fd)
+-{
+-  u_char tag = GMON_TAG_TIME_HIST;
+-  struct arc_gmon_hist_hdr thdr __attribute__ ((aligned (__alignof__ (char *))));
+-  int r;
+-
+-  if (_gmonparam.kcountsize > 0)
+-    {
+-      *(char **) thdr.low_pc = (char *) _gmonparam.lowpc;
+-      *(char **) thdr.high_pc = (char *) _gmonparam.highpc;
+-      *(int32_t *) thdr.hist_size = (_gmonparam.kcountsize
+-				     / sizeof (HISTCOUNTER));
+-      *(int32_t *) thdr.prof_rate = __profile_frequency ();
+-      strncpy (thdr.dimen, "seconds", sizeof (thdr.dimen));
+-      thdr.dimen_abbrev = 's';
+-
+-      r = write (fd, &tag, sizeof tag);
+-      if (r != sizeof tag)
+-	return;
+-      r = write (fd, &thdr, sizeof thdr);
+-      if (r != sizeof thdr)
+-	return;
+-      r = write (fd,_gmonparam.kcount, _gmonparam.kcountsize);
+-      if ((unsigned) r != _gmonparam.kcountsize)
+-	return;
+-    }
+-}
+-
+-
+-static void
+-internal_function
+-write_call_graph (int fd)
+-{
+-#define NARCS_PER_WRITE	64
+-#define BYTES_PER_ARC (1 + sizeof (struct gmon_cg_arc_record))
+-#define BYTES_PER_WRITE (BYTES_PER_ARC * NARCS_PER_WRITE)
+-  ARCINDEX to_index;
+-  u_long frompc, selfpc, count;
+-  char buffer[BYTES_PER_WRITE], *p;
+-  u_long *prof_desc = __arc_profile_desc_secstart;
+-  u_long *prof_count = __arc_profile_counters_secstart;
+-  u_long *prof_desc_end = __arc_profile_desc_secend;
+-  u_long *prof_forward = __arc_profile_forward_secstart;
+-
+-  for (p = buffer; p < buffer + BYTES_PER_WRITE; p += BYTES_PER_ARC)
+-    *p = GMON_TAG_CG_ARC;
+-  p = buffer;
+-  frompc = *prof_desc++ & -2;
+-  while (prof_desc < prof_desc_end)
+-    {
+-      selfpc = *prof_desc++;
+-      if (selfpc & 1)
+-	{
+-	  frompc = selfpc & -2;
+-	  selfpc = *prof_desc++;
+-	}
+-      count = *prof_count++;
+-      if (selfpc)
+-	{
+-	  struct arc
+-	    {
+-	      char *frompc;
+-	      char *selfpc;
+-	      int32_t count;
+-	    }
+-	  arc;
+-
+-	  if (!count)
+-	    continue;
+-	  arc.frompc = (char *) frompc;
+-	  arc.selfpc = (char *) selfpc;
+-	  arc.count  = count;
+-	  memcpy (p + 1, &arc, sizeof arc);
+-	  p += 1 + sizeof arc;
+-
+-	  if (p == buffer + BYTES_PER_WRITE)
+-	    {
+-	      write (fd, buffer, BYTES_PER_WRITE);
+-	      p = buffer;
+-	    }
+-	}
+-      else
+-	{
+-	  for (to_index = count;
+-	       to_index != 0;
+-	       to_index = _gmonparam.tos[to_index].link)
+-	    {
+-	      struct arc
+-		{
+-		  char *frompc;
+-		  char *selfpc;
+-		  int32_t count;
+-		}
+-	      arc;
+-
+-	      arc.frompc = (char *) frompc;
+-	      arc.selfpc = (char *) _gmonparam.tos[to_index].selfpc;
+-	      arc.count  = _gmonparam.tos[to_index].count;
+-	      memcpy (p + 1, &arc, sizeof arc);
+-	      p += 1 + sizeof arc;
+-
+-	      if (p == buffer + BYTES_PER_WRITE)
+-		{
+-		  write (fd, buffer, BYTES_PER_WRITE);
+-		  p = buffer;
+-		}
+-	    }
+-	}
+-    }
+-  while (prof_forward < __arc_profile_forward_secend)
+-    {
+-      /* ??? The 'call count' is actually supposed to be a fixed point
+-	 factor, with 16 bits each before and after the point.
+-	 It would be much nicer if we figured out the actual number
+-	 of calls to the caller, and multiplied that with the fixed point
+-	 factor to arrive at the estimated calls for the callee.  */
+-      memcpy (p + 1, prof_forward, 3 * sizeof *prof_forward);
+-      prof_forward += 3;
+-      p += 1 + 3 * sizeof *prof_forward;
+-      if (p == buffer + BYTES_PER_WRITE)
+-	{
+-	  write (fd, buffer, BYTES_PER_WRITE);
+-	  p = buffer;
+-	}
+-    }
+-  if (p != buffer)
+-    write (fd, buffer, p - buffer);
+-}
+-
+-
+-static void
+-internal_function
+-write_bb_counts (int fd)
+-{
+-  struct __bb *grp;
+-  u_char tag = GMON_TAG_BB_COUNT;
+-  size_t ncounts;
+-  size_t i;
+-
+-  struct { unsigned long address; long count; } bbbody[8];
+-  size_t nfilled;
+-
+-  /* Write each group of basic-block info (all basic-blocks in a
+-     compilation unit form a single group). */
+-
+-  for (grp = __bb_head; grp; grp = grp->next)
+-    {
+-      ncounts = grp->ncounts;
+-      write (fd, &tag, 1);
+-      write (fd, &ncounts, sizeof ncounts);
+-      for (nfilled = i = 0; i < ncounts; ++i)
+-	{
+-	  if (nfilled == sizeof (bbbody) / sizeof (bbbody[0]))
+-	    {
+-	      write (fd, bbbody, sizeof bbbody);
+-	      nfilled = 0;
+-	    }
+-
+-	  bbbody[nfilled].address = grp->addresses[i];
+-	  bbbody[nfilled++].count = grp->counts[i];
+-	}
+-      if (nfilled > 0)
+-	write (fd, bbbody, nfilled * sizeof bbbody[0]);
+-    }
+-}
+-
+-
+-static void
+-write_gmon (void)
+-{
+-    struct gmon_hdr ghdr __attribute__ ((aligned (__alignof__ (int))));
+-    int fd = -1;
+-    char *env;
+-
+-#ifndef O_NOFOLLOW
+-# define O_NOFOLLOW	0
+-#endif
+-
+-    env = getenv ("GMON_OUT_PREFIX");
+-    if (env != NULL && !__libc_enable_secure)
+-      {
+-	size_t len = strlen (env);
+-	char buf[len + 20];
+-	snprintf (buf, sizeof (buf), "%s.%u", env, getpid ());
+-	fd = open (buf, O_CREAT|O_TRUNC|O_WRONLY|O_NOFOLLOW, 0666);
+-      }
+-
+-    if (fd == -1)
+-      {
+-	fd = open ("gmon.out", O_CREAT|O_TRUNC|O_WRONLY|O_NOFOLLOW,
+-			      0666);
+-	if (fd < 0)
+-	  {
+-	    perror ("_mcleanup: gmon.out");
+-	    return;
+-	  }
+-      }
+-
+-    /* write gmon.out header: */
+-    memset (&ghdr, '\0', sizeof (struct gmon_hdr));
+-    memcpy (&ghdr.cookie[0], GMON_MAGIC, sizeof (ghdr.cookie));
+-    *(int32_t *) ghdr.version = GMON_VERSION;
+-    write (fd, &ghdr, sizeof (struct gmon_hdr));
+-
+-    /* write PC histogram: */
+-    write_hist (fd);
+-
+-    /* write call-graph: */
+-    write_call_graph (fd);
+-
+-    /* write basic-block execution counts: */
+-    write_bb_counts (fd);
+-
+-    close (fd);
+-}
+-
+-
+-void
+-__write_profiling (void)
+-{
+-  int save = _gmonparam.state;
+-  _gmonparam.state = GMON_PROF_OFF;
+-  if (save == GMON_PROF_ON)
+-    write_gmon ();
+-  _gmonparam.state = save;
+-}
+-#ifndef SHARED
+-/* This symbol isn't used anywhere in the DSO and it is not exported.
+-   This would normally mean it should be removed to get the same API
+-   in static libraries.  But since profiling is special in static libs
+-   anyway we keep it.  But not when building the DSO since some
+-   quality assurance tests will otherwise trigger.  */
+-weak_alias (__write_profiling, write_profiling)
+-#endif
+-
+-
+-void
+-_mcleanup (void)
+-{
+-  __moncontrol (0);
+-
+-  if (_gmonparam.state != GMON_PROF_ERROR)
+-    write_gmon ();
+-
+-  /* free the memory. */
+-  if (_gmonparam.tos != NULL)
+-    free (_gmonparam.tos);
+-}
+diff --git a/libgcc/config/arc/gmon/machine-gmon.h b/libgcc/config/arc/gmon/machine-gmon.h
+deleted file mode 100644
+index e7549aedb7cf..000000000000
+--- a/libgcc/config/arc/gmon/machine-gmon.h
++++ /dev/null
+@@ -1,65 +0,0 @@
+-/* Copyright (C) 2007-2016 Free Software Foundation, Inc.
+-   Contributor: Joern Rennecke <joern.rennecke at embecosm.com>
+-		on behalf of Synopsys Inc.
+-
+-This file is part of GCC.
+-
+-GCC is free software; you can redistribute it and/or modify it under
+-the terms of the GNU General Public License as published by the Free
+-Software Foundation; either version 3, or (at your option) any later
+-version.
+-
+-GCC is distributed in the hope that it will be useful, but WITHOUT ANY
+-WARRANTY; without even the implied warranty of MERCHANTABILITY or
+-FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+-for more details.
+-
+-Under Section 7 of GPL version 3, you are granted additional
+-permissions described in the GCC Runtime Library Exception, version
+-3.1, as published by the Free Software Foundation.
+-
+-You should have received a copy of the GNU General Public License and
+-a copy of the GCC Runtime Library Exception along with this program;
+-see the files COPYING3 and COPYING.RUNTIME respectively.  If not, see
+-<http://www.gnu.org/licenses/>.  */
+-
+-#ifndef MACHINE_GMON_H
+-#define MACHINE_GMON_H
+-
+-/* We can't fake out own <sys/types.h> header because the newlib / uclibc
+-   headers in GCC_FOR_TARGET take precedence.  */
+-
+-#define __BEGIN_DECLS
+-#define __END_DECLS
+-
+-#define __THROW
+-
+-extern int __dcache_linesz (void);
+-
+-#define _MCOUNT_DECL(countp, selfpc) \
+-  static inline void _mcount_internal (void *countp, u_long selfpc)
+-
+-extern void _mcount (void);
+-extern void _mcount_call (void);
+-
+-/* N.B.: the calling point might be a sibcall, thus blink does not necessarily
+-  hold the caller's address.  r8 doesn't hold the caller's address, either,
+-  but rather a pointer to the counter data structure associated with the
+-  caller.
+-  This function must be compiled with optimization turned on in order to
+-  enable a sibcall for the final call to selfpc; this is important when trying
+-  to profile a program with deep tail-recursion that would get a stack
+-  overflow otherwise.  */
+-#define MCOUNT \
+-void \
+-_mcount_call (void) \
+-{ \
+-  register void *countp __asm("r8"); \
+-  register u_long selfpc __asm("r9"); \
+-  _mcount_internal (countp, selfpc); \
+-  ((void (*)(void)) selfpc) (); \
+-}
+-
+-extern int __profil (u_short *,size_t, size_t, u_int);
+-
+-#endif /* MACHINE_GMON_H */
+diff --git a/libgcc/config/arc/gmon/mcount.c b/libgcc/config/arc/gmon/mcount.c
+deleted file mode 100644
+index 8afca36b88c9..000000000000
+--- a/libgcc/config/arc/gmon/mcount.c
++++ /dev/null
+@@ -1,206 +0,0 @@
+-/*-
+- * Copyright (c) 1983, 1992, 1993
+- *	The Regents of the University of California.  All rights reserved.
+- *
+- * Copyright (C) 2007-2016 Free Software Foundation, Inc.
+- *
+- * Redistribution and use in source and binary forms, with or without
+- * modification, are permitted provided that the following conditions
+- * are met:
+- * 1. Redistributions of source code must retain the above copyright
+- *    notice, this list of conditions and the following disclaimer.
+- * 2. Redistributions in binary form must reproduce the above copyright
+- *    notice, this list of conditions and the following disclaimer in the
+- *    documentation and/or other materials provided with the distribution.
+- * 4. Neither the name of the University nor the names of its contributors
+- *    may be used to endorse or promote products derived from this software
+- *    without specific prior written permission.
+- *
+- * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+- * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+- * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+- * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+- * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+- * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+- * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+- * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+- * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+- * SUCH DAMAGE.
+- */
+-
+-#if !defined(lint) && !defined(KERNEL) && defined(LIBC_SCCS)
+-static char sccsid[] = "@(#)mcount.c	8.1 (Berkeley) 6/4/93";
+-#endif
+-
+-#if 0
+-#include <unistd.h>
+-#include <sys/param.h>
+-#endif
+-#include <sys/gmon.h>
+-
+-/* This file provides the machine-dependent definitions of the _MCOUNT_DECL
+-   and MCOUNT macros.  */
+-#include <machine-gmon.h>
+-
+-#include <atomic.h>
+-
+-/*
+- * mcount is called on entry to each function compiled with the profiling
+- * switch set.  _mcount(), which is declared in a machine-dependent way
+- * with _MCOUNT_DECL, does the actual work and is either inlined into a
+- * C routine or called by an assembly stub.  In any case, this magic is
+- * taken care of by the MCOUNT definition in <machine/profile.h>.
+- *
+- * _mcount updates data structures that represent traversals of the
+- * program's call graph edges.  frompc and selfpc are the return
+- * address and function address that represents the given call graph edge.
+- *
+- * Note: the original BSD code used the same variable (frompcindex) for
+- * both frompcindex and frompc.  Any reasonable, modern compiler will
+- * perform this optimization.
+- */
+-_MCOUNT_DECL(count_ptr, selfpc)	/* _mcount; may be static, inline, etc */
+-{
+-	register ARCINDEX *frompcindex;
+-	register struct tostruct *top, *prevtop;
+-	register struct gmonparam *p;
+-	register ARCINDEX toindex;
+-
+-	/* Check for nested function trampoline.  */
+-	if (selfpc & 2)
+-	  selfpc = *(u_long *) (selfpc + 10);
+-
+-	p = &_gmonparam;
+-	/*
+-	 * check that we are profiling
+-	 * and that we aren't recursively invoked.
+-	 */
+-#if 0
+-	if (catomic_compare_and_exchange_bool_acq (&p->state, GMON_PROF_BUSY,
+-						   GMON_PROF_ON))
+-	  return;
+-#elif defined (__ARC700__)
+-/* ??? This could temporarily lose the ERROR / OFF condition in a race,
+-   but doing an actual compare_and_exchange would be too costly.  It would
+-   be better if we had a semaphore independent of the 'sticky' state, but
+-   then we could run into ABI compatibility problems with the size of struct
+-   gmonparam.  */
+-	{
+-	  u_long old_state;
+-
+-	  __asm ("ex %0,%1": "=r" (old_state), "+m" (p->state)
+-		 : "0" (GMON_PROF_BUSY));
+-	  if (old_state != GMON_PROF_ON)
+-	    {
+-	      switch (old_state)
+-		{
+-		case GMON_PROF_OFF:
+-		  __asm ("ex %0,%1": "+r" (old_state), "+m" (p->state));
+-		  if (old_state == GMON_PROF_BUSY
+-		      /* Switching off while we say we are busy while profiling
+-			 was actually already switched off is all right.  */
+-		      || old_state == GMON_PROF_OFF)
+-		    break;
+-		  /* It is not clear if we should allow switching on
+-		     profiling at this point, and how to handle further races.
+-		     For now, record an error in this case.  */
+-		  /* Fall through.  */
+-		default: /* We expect here only GMON_PROF_ERROR.  */
+-		  p->state = GMON_PROF_ERROR;
+-		  break;
+-		case GMON_PROF_BUSY: break;
+-		}
+-	      return;
+-	    }
+-	}
+-#else /* ??? No semaphore primitives available.  */
+-	if (p->state != GMON_PROF_ON)
+-	  return;
+-	p->state = GMON_PROF_BUSY;
+-#endif
+-
+-	frompcindex = count_ptr;
+-	toindex = *frompcindex;
+-	if (toindex == 0) {
+-		/*
+-		 *	first time traversing this arc
+-		 */
+-		toindex = ++p->tos[0].link;
+-		if (toindex >= (ARCINDEX) p->tolimit)
+-			/* halt further profiling */
+-			goto overflow;
+-
+-		*frompcindex = toindex;
+-		top = &p->tos[toindex];
+-		top->selfpc = selfpc;
+-		top->count = 1;
+-		top->link = 0;
+-		goto done;
+-	}
+-	top = &p->tos[toindex];
+-	if (top->selfpc == selfpc) {
+-		/*
+-		 * arc at front of chain; usual case.
+-		 */
+-		top->count++;
+-		goto done;
+-	}
+-	/*
+-	 * have to go looking down chain for it.
+-	 * top points to what we are looking at,
+-	 * prevtop points to previous top.
+-	 * we know it is not at the head of the chain.
+-	 */
+-	for (; /* goto done */; ) {
+-		if (top->link == 0) {
+-			/*
+-			 * top is end of the chain and none of the chain
+-			 * had top->selfpc == selfpc.
+-			 * so we allocate a new tostruct
+-			 * and link it to the head of the chain.
+-			 */
+-			toindex = ++p->tos[0].link;
+-			if (toindex >= (ARCINDEX) p->tolimit)
+-				goto overflow;
+-
+-			top = &p->tos[toindex];
+-			top->selfpc = selfpc;
+-			top->count = 1;
+-			top->link = *frompcindex;
+-			*frompcindex = toindex;
+-			goto done;
+-		}
+-		/*
+-		 * otherwise, check the next arc on the chain.
+-		 */
+-		prevtop = top;
+-		top = &p->tos[top->link];
+-		if (top->selfpc == selfpc) {
+-			/*
+-			 * there it is.
+-			 * increment its count
+-			 * move it to the head of the chain.
+-			 */
+-			top->count++;
+-			toindex = prevtop->link;
+-			prevtop->link = top->link;
+-			top->link = *frompcindex;
+-			*frompcindex = toindex;
+-			goto done;
+-		}
+-
+-	}
+-done:
+-	p->state = GMON_PROF_ON;
+-	return;
+-overflow:
+-	p->state = GMON_PROF_ERROR;
+-	return;
+-}
+-
+-/*
+- * Actual definition of mcount function.  Defined in <machine/profile.h>,
+- * which is included by <sys/gmon.h>.
+- */
+-MCOUNT
+diff --git a/libgcc/config/arc/gmon/prof-freq-stub.S b/libgcc/config/arc/gmon/prof-freq-stub.S
+deleted file mode 100644
+index 9ffb30b9736d..000000000000
+--- a/libgcc/config/arc/gmon/prof-freq-stub.S
++++ /dev/null
+@@ -1,40 +0,0 @@
+-/* This file contains code to do profiling.
+-
+-   Copyright (C) 2007-2016 Free Software Foundation, Inc.
+-   Contributor: Joern Rennecke <joern.rennecke at embecosm.com>
+-		on behalf of Synopsys Inc.
+-
+-This file is part of GCC.
+-
+-GCC is free software; you can redistribute it and/or modify it under
+-the terms of the GNU General Public License as published by the Free
+-Software Foundation; either version 3, or (at your option) any later
+-version.
+-
+-GCC is distributed in the hope that it will be useful, but WITHOUT ANY
+-WARRANTY; without even the implied warranty of MERCHANTABILITY or
+-FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+-for more details.
+-
+-Under Section 7 of GPL version 3, you are granted additional
+-permissions described in the GCC Runtime Library Exception, version
+-3.1, as published by the Free Software Foundation.
+-
+-You should have received a copy of the GNU General Public License and
+-a copy of the GCC Runtime Library Exception along with this program;
+-see the files COPYING3 and COPYING.RUNTIME respectively.  If not, see
+-<http://www.gnu.org/licenses/>.  */
+-
+-#include "../asm.h"
+-/*  This file contains code to do profiling.  */
+-	.weak	__profile_frequency_value
+-	.global __profile_frequency_value
+-	.set	__profile_frequency_value, 1000
+-	.text
+-	.balign	4
+-	.global __profile_frequency
+-	FUNC(__profile_frequency)
+-__profile_frequency:
+-	mov_s	r0,__profile_frequency_value
+-	j_s	[blink]
+-	ENDFUNC(__profile_frequency)
+diff --git a/libgcc/config/arc/gmon/prof-freq.c b/libgcc/config/arc/gmon/prof-freq.c
+deleted file mode 100644
+index 4437a37d80a8..000000000000
+--- a/libgcc/config/arc/gmon/prof-freq.c
++++ /dev/null
+@@ -1,60 +0,0 @@
+-/* Return frequency of ticks reported by profil.  Generic version. */
+-/*-
+- * Copyright (c) 1983, 1992, 1993
+- *	The Regents of the University of California.  All rights reserved.
+- *
+- * Copyright (C) 2007-2016 Free Software Foundation, Inc.
+- *
+- * Redistribution and use in source and binary forms, with or without
+- * modification, are permitted provided that the following conditions
+- * are met:
+- * 1. Redistributions of source code must retain the above copyright
+- *    notice, this list of conditions and the following disclaimer.
+- * 2. Redistributions in binary form must reproduce the above copyright
+- *    notice, this list of conditions and the following disclaimer in the
+- *    documentation and/or other materials provided with the distribution.
+- * 4. Neither the name of the University nor the names of its contributors
+- *    may be used to endorse or promote products derived from this software
+- *    without specific prior written permission.
+- *
+- * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+- * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+- * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+- * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+- * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+- * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+- * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+- * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+- * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+- * SUCH DAMAGE.
+- */
+-
+-
+-#include <sys/types.h>
+-#include <sys/time.h>
+-#if 0
+-#include <libc-internal.h>
+-#else
+-#include "sys/gmon.h"
+-#endif
+-
+-int
+-__profile_frequency (void)
+-{
+-  /*
+-   * Discover the tick frequency of the machine if something goes wrong,
+-   * we return 0, an impossible hertz.
+-   */
+-  struct itimerval tim;
+-
+-  tim.it_interval.tv_sec = 0;
+-  tim.it_interval.tv_usec = 1;
+-  tim.it_value.tv_sec = 0;
+-  tim.it_value.tv_usec = 0;
+-  setitimer(ITIMER_REAL, &tim, 0);
+-  setitimer(ITIMER_REAL, 0, &tim);
+-  if (tim.it_interval.tv_usec < 2)
+-    return 0;
+-  return (1000000 / tim.it_interval.tv_usec);
+-}
+diff --git a/libgcc/config/arc/gmon/profil.S b/libgcc/config/arc/gmon/profil.S
+deleted file mode 100644
+index 807e9fe60cc7..000000000000
+--- a/libgcc/config/arc/gmon/profil.S
++++ /dev/null
+@@ -1,164 +0,0 @@
+-/* This file contains code to do profiling.
+-
+-   Copyright (C) 2007-2016 Free Software Foundation, Inc.
+-   Contributor: Joern Rennecke <joern.rennecke at embecosm.com>
+-		on behalf of Synopsys Inc.
+-
+-
+-This file is part of GCC.
+-
+-GCC is free software; you can redistribute it and/or modify it under
+-the terms of the GNU General Public License as published by the Free
+-Software Foundation; either version 3, or (at your option) any later
+-version.
+-
+-GCC is distributed in the hope that it will be useful, but WITHOUT ANY
+-WARRANTY; without even the implied warranty of MERCHANTABILITY or
+-FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+-for more details.
+-
+-Under Section 7 of GPL version 3, you are granted additional
+-permissions described in the GCC Runtime Library Exception, version
+-3.1, as published by the Free Software Foundation.
+-
+-You should have received a copy of the GNU General Public License and
+-a copy of the GCC Runtime Library Exception along with this program;
+-see the files COPYING3 and COPYING.RUNTIME respectively.  If not, see
+-<http://www.gnu.org/licenses/>.  */
+-
+-#include "../asm.h"
+-#include "auxreg.h"
+-/*  This file contains code to do profiling.  */
+-	.weak	__profile_timer_cycles
+-	.global __profile_timer_cycles
+-	.set	__profile_timer_cycles, 200
+-
+-        .section .bss
+-        .global __profil_offset
+-        .align 4
+-        .type	__profil_offset, @object
+-        .size	__profil_offset, 4
+-__profil_offset:
+-        .zero   4
+-
+-	.text
+-	.global	__dcache_linesz
+-	.global __profil
+-	FUNC(__profil)
+-#if !defined (__EM__) && !defined (__HS__)
+-.Lstop_profiling:
+-	sr	r0,[CONTROL0]
+-	j_s	[blink]
+-	.balign	4
+-__profil:
+-.Lprofil:
+-	breq_s	r0,0,.Lstop_profiling
+-	; r0: buf r1: bufsiz r2: offset r3: scale
+-	bxor.f	r3,r3,15; scale must be 0x8000, i.e. 1/2; generate 0.
+-	push_s	blink
+-	lsr_s	r2,r2,1
+-	mov_s	r8,r0
+-	flag.ne	1	; halt if wrong scale
+-	sub_s	r0,r0,r2
+-	st	r0,[__profil_offset]
+-	bl	__dcache_linesz
+-	pop_s	blink
+-	bbit1.d	r0,0,nocache
+-	mov_s	r0,r8
+-#ifdef __ARC700__
+-	add_s	r1,r1,31
+-	lsr.f	lp_count,r1,5
+-	lpne	2f
+-	sr	r0,[DC_FLDL]
+-	add_s	r0,r0,32
+-#else /* !__ARC700__ */
+-# FIX ME: set up loop according to cache line size
+-	lr	r12,[D_CACHE_BUILD]
+-	sub_s	r0,r0,16
+-	sub_s	r1,r1,1
+-	lsr_s	r12,r12,16
+-	asr_s	r1,r1,4
+-	bmsk_s	r12,r12,3
+-	asr_s	r1,r1,r12
+-	add.f	lp_count,r1,1
+-	mov_s	r1,16
+-	asl_s	r1,r1,r12
+-	lpne	2f
+-	add	r0,r0,r1
+-	sr	r0,[DC_FLDL]
+-#endif /* __ARC700__ */
+-2:	b_s	.Lcounters_cleared
+-nocache:
+-.Lcounters_cleared:
+-	lr	r1,[INT_VECTOR_BASE] ; disable timer0 interrupts
+-	sr	r3,[CONTROL0]
+-	sr	r3,[COUNT0]
+-0:	ld_s	r0,[pcl,1f-0b+((0b-.Lprofil) & 2)] ; 1f at GOTOFF
+-0:	ld_s	r12,[pcl,1f+4-0b+((0b-.Lprofil) & 2)] ; 1f at GOTOFF + 4
+-	st_s	r0,[r1,24]; timer0 uses vector3
+-	st_s	r12,[r1,24+4]; timer0 uses vector3
+-	;sr	10000,[LIMIT0]
+-	sr	__profile_timer_cycles,[LIMIT0]
+-	mov_s	r12,3	; enable timer interrupts; count only when not halted.
+-	sr	r12,[CONTROL0]
+-	lr	r12,[STATUS32]
+-	bset_s	r12,r12,1 ; allow level 1 interrupts
+-	flag	r12
+-	mov_s	r0,0
+-	j_s	[blink]
+-	.balign	4
+-1:	j	__profil_irq
+-#else
+-__profil:
+-	.balign	4
+-	mov_s	r0,-1
+-	j_s	[blink]
+-#endif /* !__EM__ && !__HS__ */
+-	ENDFUNC(__profil)
+-
+-	FUNC(__profil_irq)
+-	.balign 4	; make final jump unaligned to avoid delay penalty
+-	.balign 32,0,12	; make sure the code spans no more that two cache lines
+-	nop_s
+-__profil_irq:
+-#if !defined (__EM__) && !defined (__HS__)
+-	push_s	r0
+-	ld	r0,[__profil_offset]
+-	push_s	r1
+-	lsr	r1,ilink1,2
+-	push_s	r2
+-	ldw.as.di r2,[r0,r1]
+-	add1	r0,r0,r1
+-	ld_s	r1,[sp,4]
+-	add_s	r2,r2,1
+-	bbit1	r2,16,nostore
+-	stw.di	r2,[r0]
+-nostore:ld.ab	r2,[sp,8]
+-	pop_s	r0
+-	j.f	[ilink1]
+-#else
+-	rtie
+-#endif /* !__EM__  && !__HS__ */
+-	ENDFUNC(__profil_irq)
+-
+-; could save one cycle if the counters were allocated at link time and
+-; the contents of __profil_offset were pre-computed at link time, like this:
+-#if 0
+-; __profil_offset needs to be PROVIDEd as __profile_base-text/4
+-	.global	__profil_offset
+-	.balign 4
+-__profil_irq:
+-	push_s	r0
+-	lsr	r0,ilink1,2
+-	add1	r0,__profil_offset,r0
+-	push_s	r1
+-	ldw.di	r1,[r0]
+-
+-
+-	add_s	r1,r1,1
+-	bbit1	r1,16,nostore
+-	stw.di	r1,[r0]
+-nostore:pop_s	r1
+-	pop_s	r0
+-	j	[ilink1]
+-#endif /* 0 */
+diff --git a/libgcc/config/arc/gmon/sys/gmon.h b/libgcc/config/arc/gmon/sys/gmon.h
+deleted file mode 100644
+index f17165a3a823..000000000000
+--- a/libgcc/config/arc/gmon/sys/gmon.h
++++ /dev/null
+@@ -1,217 +0,0 @@
+-/*-
+- * Copyright (c) 1982, 1986, 1992, 1993
+- *	The Regents of the University of California.  All rights reserved.
+- * Copyright (C) 2007-2016 Free Software Foundation, Inc.
+- *
+- * Redistribution and use in source and binary forms, with or without
+- * modification, are permitted provided that the following conditions
+- * are met:
+- * 1. Redistributions of source code must retain the above copyright
+- *    notice, this list of conditions and the following disclaimer.
+- * 2. Redistributions in binary form must reproduce the above copyright
+- *    notice, this list of conditions and the following disclaimer in the
+- *    documentation and/or other materials provided with the distribution.
+- * 4. Neither the name of the University nor the names of its contributors
+- *    may be used to endorse or promote products derived from this software
+- *    without specific prior written permission.
+- *
+- * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+- * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+- * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+- * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+- * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+- * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+- * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+- * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+- * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+- * SUCH DAMAGE.
+- *
+- *	@(#)gmon.h	8.2 (Berkeley) 1/4/94
+- */
+-
+-#ifndef	_SYS_GMON_H
+-#define	_SYS_GMON_H	1
+-
+-#if 0
+-#include <features.h>
+-#include <sys/types.h>
+-#else
+-#include <sys/types.h>
+-#include "machine-gmon.h"
+-#define attribute_hidden __attribute__ ((visibility("hidden")))
+-#endif
+-
+-#include <stdint.h>
+-
+-/*
+- * See gmon_out.h for gmon.out format.
+- */
+-
+-/* structure emitted by "gcc -a".  This must match struct bb in
+-   gcc/libgcc2.c.  It is OK for gcc to declare a longer structure as
+-   long as the members below are present.  */
+-struct __bb
+-{
+-  long			zero_word;
+-  const char		*filename;
+-  long			*counts;
+-  long			ncounts;
+-  struct __bb		*next;
+-  const unsigned long	*addresses;
+-};
+-
+-extern struct __bb *__bb_head;
+-
+-/*
+- * histogram counters are unsigned shorts (according to the kernel).
+- */
+-#define	HISTCOUNTER	unsigned short
+-
+-/*
+- * fraction of text space to allocate for histogram counters here, 1/2
+- */
+-#define	HISTFRACTION	2
+-
+-/*
+- * Fraction of text space to allocate for from hash buckets.
+- * The value of HASHFRACTION is based on the minimum number of bytes
+- * of separation between two subroutine call points in the object code.
+- * Given MIN_SUBR_SEPARATION bytes of separation the value of
+- * HASHFRACTION is calculated as:
+- *
+- *	HASHFRACTION = MIN_SUBR_SEPARATION / (2 * sizeof(short) - 1);
+- *
+- * For example, on the VAX, the shortest two call sequence is:
+- *
+- *	calls	$0,(r0)
+- *	calls	$0,(r0)
+- *
+- * which is separated by only three bytes, thus HASHFRACTION is
+- * calculated as:
+- *
+- *	HASHFRACTION = 3 / (2 * 2 - 1) = 1
+- *
+- * Note that the division above rounds down, thus if MIN_SUBR_FRACTION
+- * is less than three, this algorithm will not work!
+- *
+- * In practice, however, call instructions are rarely at a minimal
+- * distance.  Hence, we will define HASHFRACTION to be 2 across all
+- * architectures.  This saves a reasonable amount of space for
+- * profiling data structures without (in practice) sacrificing
+- * any granularity.
+- */
+-#define	HASHFRACTION	2
+-
+-/*
+- * Percent of text space to allocate for tostructs.
+- * This is a heuristic; we will fail with a warning when profiling programs
+- * with a very large number of very small functions, but that's
+- * normally OK.
+- * 2 is probably still a good value for normal programs.
+- * Profiling a test case with 64000 small functions will work if
+- * you raise this value to 3 and link statically (which bloats the
+- * text size, thus raising the number of arcs expected by the heuristic).
+- */
+-#define ARCDENSITY	3
+-
+-/*
+- * Always allocate at least this many tostructs.  This
+- * hides the inadequacy of the ARCDENSITY heuristic, at least
+- * for small programs.
+- */
+-#define MINARCS		50
+-
+-/*
+- * The type used to represent indices into gmonparam.tos[].
+- */
+-#define	ARCINDEX	u_long
+-
+-/* 
+- * Maximum number of arcs we want to allow.
+- * Used to be max representable value of ARCINDEX minus 2, but now 
+- * that ARCINDEX is a long, that's too large; we don't really want 
+- * to allow a 48 gigabyte table.
+- * The old value of 1<<16 wasn't high enough in practice for large C++
+- * programs; will 1<<20 be adequate for long?  FIXME
+- */
+-#define MAXARCS		(1 << 20)
+-
+-struct tostruct {
+-	u_long		selfpc;
+-	long		count;
+-	ARCINDEX	link;
+-};
+-
+-/*
+- * a raw arc, with pointers to the calling site and
+- * the called site and a count.
+- */
+-struct rawarc {
+-	u_long	raw_frompc;
+-	u_long	raw_selfpc;
+-	long	raw_count;
+-};
+-
+-/*
+- * general rounding functions.
+- */
+-#define ROUNDDOWN(x,y)	(((x)/(y))*(y))
+-#define ROUNDUP(x,y)	((((x)+(y)-1)/(y))*(y))
+-
+-/*
+- * The profiling data structures are housed in this structure.
+- */
+-struct gmonparam {
+-	long int	state;
+-	u_short		*kcount;
+-	u_long		kcountsize;
+-	ARCINDEX	*froms;
+-	u_long		fromssize;
+-	struct tostruct	*tos;
+-	u_long		tossize;
+-	long		tolimit;
+-	u_long		lowpc;
+-	u_long		highpc;
+-	u_long		textsize;
+-	u_long		hashfraction;
+-	long		log_hashfraction;
+-};
+-extern struct gmonparam _gmonparam;
+-
+-/*
+- * Possible states of profiling.
+- */
+-#define	GMON_PROF_ON	0
+-#define	GMON_PROF_BUSY	1
+-#define	GMON_PROF_ERROR	2
+-#define	GMON_PROF_OFF	3
+-
+-/*
+- * Sysctl definitions for extracting profiling information from the kernel.
+- */
+-#define	GPROF_STATE	0	/* int: profiling enabling variable */
+-#define	GPROF_COUNT	1	/* struct: profile tick count buffer */
+-#define	GPROF_FROMS	2	/* struct: from location hash bucket */
+-#define	GPROF_TOS	3	/* struct: destination/count structure */
+-#define	GPROF_GMONPARAM	4	/* struct: profiling parameters (see above) */
+-
+-__BEGIN_DECLS
+-
+-/* Set up data structures and start profiling.  */
+-extern void __monstartup (u_long __lowpc, u_long __highpc) __THROW;
+-extern void monstartup (u_long __lowpc, u_long __highpc) __THROW;
+-
+-/* Clean up profiling and write out gmon.out.  */
+-extern void _mcleanup (void) __THROW;
+-
+-extern void __write_profiling (void);
+-extern int attribute_hidden __profile_frequency (void);
+-
+-extern u_long __arc_profile_desc_secstart[], __arc_profile_desc_secend[];
+-extern u_long __arc_profile_forward_secstart[], __arc_profile_forward_secend[];
+-extern u_long __arc_profile_counters_secstart[];
+-
+-__END_DECLS
+-
+-#endif /* sys/gmon.h */
+diff --git a/libgcc/config/arc/gmon/sys/gmon_out.h b/libgcc/config/arc/gmon/sys/gmon_out.h
+deleted file mode 100644
+index d1f3b058a815..000000000000
+--- a/libgcc/config/arc/gmon/sys/gmon_out.h
++++ /dev/null
+@@ -1,55 +0,0 @@
+-/* Copyright (C) 2007-2016 Free Software Foundation, Inc.
+-   Contributor: Joern Rennecke <joern.rennecke at embecosm.com>
+-		on behalf of Synopsys Inc.
+-
+-This file is part of GCC.
+-
+-GCC is free software; you can redistribute it and/or modify it under
+-the terms of the GNU General Public License as published by the Free
+-Software Foundation; either version 3, or (at your option) any later
+-version.
+-
+-GCC is distributed in the hope that it will be useful, but WITHOUT ANY
+-WARRANTY; without even the implied warranty of MERCHANTABILITY or
+-FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+-for more details.
+-
+-Under Section 7 of GPL version 3, you are granted additional
+-permissions described in the GCC Runtime Library Exception, version
+-3.1, as published by the Free Software Foundation.
+-
+-You should have received a copy of the GNU General Public License and
+-a copy of the GCC Runtime Library Exception along with this program;
+-see the files COPYING3 and COPYING.RUNTIME respectively.  If not, see
+-<http://www.gnu.org/licenses/>.  */
+-
+-#define GMON_TAG_TIME_HIST 0
+-#define GMON_TAG_CG_ARC 1
+-#define GMON_TAG_BB_COUNT 2
+-
+-#define GMON_MAGIC "gmon"
+-#define GMON_VERSION 1
+-
+-struct arc_gmon_hist_hdr
+-{
+-  char low_pc[4];
+-  char high_pc[4];
+-  char hist_size[4];
+-  char prof_rate[4];
+-  char dimen[15];
+-  char dimen_abbrev;
+-};
+-
+-struct gmon_cg_arc_record
+-{
+-  char afrompc[4];
+-  char selfpc[4];
+-  char count[4];
+-};
+-
+-struct gmon_hdr
+-{
+-  char cookie[4];
+-  char version[4];
+-  char c[12];
+-};
+diff --git a/libgcc/config/arc/t-arc b/libgcc/config/arc/t-arc
+index 3523aedec13b..51a9273ec23b 100644
+--- a/libgcc/config/arc/t-arc
++++ b/libgcc/config/arc/t-arc
+@@ -62,42 +62,5 @@ fp-bit.c: $(srcdir)/fp-bit.c
+ 
+ # .init/.fini section routines
+ 
+-crtg.o: $(srcdir)/config/arc/crtg.S
+-	$(crt_compile) -c -x assembler-with-cpp $<
+-
+-crtgend.o: $(srcdir)/config/arc/crtgend.S
+-	$(crt_compile) -c -x assembler-with-cpp $<
+-
+ crttls.o: $(srcdir)/config/arc/crttls.S
+ 	$(crt_compile) -c -x assembler-with-cpp $<
+-
+-mcount.o: $(srcdir)/config/arc/gmon/mcount.c
+-	$(gcc_compile) -isystem $(srcdir)/config/arc/gmon -c $< \
+-	-fcall-saved-r0 -fcall-saved-r1 -fcall-saved-r2 -fcall-saved-r3 \
+-	-fcall-saved-r4 -fcall-saved-r5 -fcall-saved-r6 -fcall-saved-r7 \
+-	-fomit-frame-pointer
+-
+-gmon.o: $(srcdir)/config/arc/gmon/gmon.c
+-	$(gcc_compile) -isystem $(srcdir)/config/arc/gmon -mno-sdata -c $< \
+-	-fno-strict-aliasing \
+-	-Wno-extra # suppress inane warning about missing initializer.
+-	# Adding initializers for the remaining elements of gmonparam would
+-	# make the code more brittle.
+-
+-prof-freq-stub.o: $(srcdir)/config/arc/gmon/prof-freq-stub.S
+-	$(gcc_compile) -isystem $(srcdir)/config/arc/gmon -c $<
+-
+-prof-freq.o: $(srcdir)/config/arc/gmon/prof-freq.c
+-	$(gcc_compile) -isystem $(srcdir)/config/arc/gmon -c $<
+-
+-dcache_linesz.o: $(srcdir)/config/arc/gmon/dcache_linesz.S
+-	$(gcc_compile) -isystem $(srcdir)/config/arc/gmon -c $<
+-
+-profil.o: $(srcdir)/config/arc/gmon/profil.S
+-	$(gcc_compile) -isystem $(srcdir)/config/arc/gmon -c $<
+-
+-profil-uclibc.o: $(srcdir)/config/arc/gmon/profil-uclibc.c
+-	$(gcc_compile) -isystem $(srcdir)/config/arc/gmon -c $<
+-
+-libgmon.a: mcount.o gmon.o dcache_linesz.o $(PROFILE_OSDEP)
+-	$(AR_CREATE_FOR_TARGET) $@ $^
+diff --git a/libgcc/config/arc/t-arc-newlib b/libgcc/config/arc/t-arc-newlib
+deleted file mode 100644
+index f56b05259f03..000000000000
+--- a/libgcc/config/arc/t-arc-newlib
++++ /dev/null
+@@ -1,22 +0,0 @@
+-# GCC Makefile fragment for the Synopsys DesignWare ARC CPU with newlib.
+-
+-# Copyright (C) 2007-2016 Free Software Foundation, Inc.
+-# Contributor: Joern Rennecke <joern.rennecke at embecosm.com>
+-#              on behalf of Synopsys Inc.
+-
+-# This file is part of GCC.
+-
+-# GCC is free software; you can redistribute it and/or modify it under the
+-# terms of the GNU General Public License as published by the Free Software
+-# Foundation; either version 3, or (at your option) any later version.
+-
+-# GCC is distributed in the hope that it will be useful, but WITHOUT ANY
+-# WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
+-# FOR A PARTICULAR PURPOSE.  See the GNU General Public License for more
+-# details.
+-
+-# You should have received a copy of the GNU General Public License along
+-# with GCC; see the file COPYING3.  If not see
+-# <http://www.gnu.org/licenses/>.
+-
+-PROFILE_OSDEP = prof-freq-stub.o profil.o
+diff --git a/libgcc/config/arc/t-arc700-uClibc b/libgcc/config/arc/t-arc-uClibc
+similarity index 98%
+rename from libgcc/config/arc/t-arc700-uClibc
+rename to libgcc/config/arc/t-arc-uClibc
+index f5067cc01924..81156e8dc550 100644
+--- a/libgcc/config/arc/t-arc700-uClibc
++++ b/libgcc/config/arc/t-arc-uClibc
+@@ -33,8 +33,6 @@ CRTSTUFF_T_CFLAGS_S = $(CRTSTUFF_T_CFLAGS) -fPIC
+ # Compile libgcc2.a with pic.
+ TARGET_LIBGCC2_CFLAGS = -fPIC
+ 
+-PROFILE_OSDEP = prof-freq.o
+-
+ # Override t-slibgcc-elf-ver to hide some lib1func
+ # routines which should not be called via PLT.
+ SHLIB_MAPFILES = libgcc-std.ver $(srcdir)/config/arc/libgcc-excl.ver
+-- 
+2.7.4
+
diff --git a/toolchain/gcc/patches/6.3.0/0040-ARC-Clean-up-arc-header-file.patch b/toolchain/gcc/patches/6.3.0/0040-ARC-Clean-up-arc-header-file.patch
new file mode 100644
index 0000000..0457d6c
--- /dev/null
+++ b/toolchain/gcc/patches/6.3.0/0040-ARC-Clean-up-arc-header-file.patch
@@ -0,0 +1,501 @@
+From cb3e1052fbbbde47c876fdb45e824879e080ba36 Mon Sep 17 00:00:00 2001
+From: Claudiu Zissulescu <claziss at synopsys.com>
+Date: Fri, 29 Jul 2016 15:30:00 +0200
+Subject: [PATCH 40/89] [ARC] Clean up arc header file.
+
+gcc/
+2016-07-29  Claudiu Zissulescu  <claziss at synopsys.com>
+
+	* config.gcc (arc*-): Clean up, use arc/big.h, arc/elf.h, and
+	arc/linux.h headers.
+	* config/arc/arc.h (TARGET_OS_CPP_BUILTINS): Remove.
+	(LINK_SPEC): Likewise.
+	(ARC_TLS_EXTRA_START_SPEC): Likewise.
+	(EXTRA_SPECS): Likewise.
+	(STARTFILE_SPEC): Likewise.
+	(ENDFILE_SPEC): Likewise.
+	(LIB_SPEC): Likewise.
+	(TARGET_SDATA_DEFAULT): Likewise.
+	(TARGET_MMEDIUM_CALLS_DEFAULT): Likewise.
+	(MULTILIB_DEFAULTS): Likewise.
+	(DWARF2_UNWIND_INFO): Likewise.
+	* config/arc/big.h: New file.
+	* config/arc/elf.h: Likewise.
+	* config/arc/linux.h: Likewise.
+	* config/arc/t-uClibc: Remove.
+---
+ gcc/config.gcc          |  15 +++---
+ gcc/config/arc/arc.h    | 120 +++++-------------------------------------------
+ gcc/config/arc/big.h    |  22 +++++++++
+ gcc/config/arc/elf.h    |  55 ++++++++++++++++++++++
+ gcc/config/arc/linux.h  |  76 ++++++++++++++++++++++++++++++
+ gcc/config/arc/t-uClibc |  20 --------
+ 6 files changed, 171 insertions(+), 137 deletions(-)
+ create mode 100644 gcc/config/arc/big.h
+ create mode 100644 gcc/config/arc/elf.h
+ create mode 100644 gcc/config/arc/linux.h
+ delete mode 100644 gcc/config/arc/t-uClibc
+
+diff --git a/gcc/config.gcc b/gcc/config.gcc
+index 7b6138aec6bf..972f8f3ac130 100644
+--- a/gcc/config.gcc
++++ b/gcc/config.gcc
+@@ -326,6 +326,7 @@ arc*-*-*)
+ 	c_target_objs="arc-c.o"
+ 	cxx_target_objs="arc-c.o"
+ 	extra_options="${extra_options} arc/arc-tables.opt"
++	extra_headers="arc-simd.h"
+ 	;;
+ arm*-*-*)
+ 	cpu_type=arm
+@@ -1002,8 +1003,7 @@ alpha*-dec-*vms*)
+ 	tmake_file="${tmake_file} alpha/t-vms"
+ 	;;
+ arc*-*-elf*)
+-	extra_headers="arc-simd.h"
+-	tm_file="arc/arc-arch.h dbxelf.h elfos.h newlib-stdint.h ${tm_file}"
++	tm_file="arc/arc-arch.h dbxelf.h elfos.h newlib-stdint.h arc/elf.h ${tm_file}"
+ 	tmake_file="arc/t-multilib arc/t-arc"
+ 	extra_gcc_objs="driver-arc.o"
+ 	if test "x$with_cpu" != x; then
+@@ -1020,15 +1020,12 @@ arc*-*-elf*)
+ 	*)	echo "with_endian=${with_endian} not supported."; exit 1 ;;
+ 	esac
+ 	case ${with_endian} in
+-	big*)	tm_defines="DRIVER_ENDIAN_SELF_SPECS=\\\"%{!EL:%{!mlittle-endian:-mbig-endian}}\\\" ${tm_defines}"
++	big*)	tm_file="arc/big.h ${tm_file}"
+ 	esac
+ 	;;
+ arc*-*-linux-uclibc*)
+-	extra_headers="arc-simd.h"
+-	tm_file="arc/arc-arch.h dbxelf.h elfos.h gnu-user.h linux.h linux-android.h glibc-stdint.h ${tm_file}"
+-	tmake_file="${tmake_file} arc/t-uClibc arc/t-arc"
+-	tm_defines="${tm_defines} TARGET_SDATA_DEFAULT=0"
+-	tm_defines="${tm_defines} TARGET_MMEDIUM_CALLS_DEFAULT=1"
++	tm_file="arc/arc-arch.h dbxelf.h elfos.h gnu-user.h linux.h linux-android.h glibc-stdint.h arc/linux.h ${tm_file}"
++	tmake_file="${tmake_file} arc/t-arc"
+ 	extra_gcc_objs="driver-arc.o"
+ 	if test "x$with_cpu" != x; then
+ 		tm_defines="${tm_defines} TARGET_CPU_BUILD=PROCESSOR_$with_cpu"
+@@ -1044,7 +1041,7 @@ arc*-*-linux-uclibc*)
+ 	*)	echo "with_endian=${with_endian} not supported."; exit 1 ;;
+ 	esac
+ 	case ${with_endian} in
+-	big*)	tm_defines="DRIVER_ENDIAN_SELF_SPECS=\\\"%{!EL:%{!mlittle-endian:-mbig-endian}}\\\" ${tm_defines}"
++	big*)	tm_file="arc/big.h ${tm_file}"
+ 	esac
+         ;;
+ arm-wrs-vxworks)
+diff --git a/gcc/config/arc/arc.h b/gcc/config/arc/arc.h
+index 3df21d416d97..5ca2bb5ffcd0 100644
+--- a/gcc/config/arc/arc.h
++++ b/gcc/config/arc/arc.h
+@@ -1,14 +1,6 @@
+ /* Definitions of target machine for GNU compiler, Synopsys DesignWare ARC cpu.
+    Copyright (C) 1994-2016 Free Software Foundation, Inc.
+ 
+-   Sources derived from work done by Sankhya Technologies (www.sankhya.com) on
+-   behalf of Synopsys Inc.
+-
+-   Position Independent Code support added,Code cleaned up,
+-   Comments and Support For ARC700 instructions added by
+-   Saurabh Verma (saurabh.verma at codito.com)
+-   Ramana Radhakrishnan(ramana.radhakrishnan at codito.com)
+-
+ This file is part of GCC.
+ 
+ GCC is free software; you can redistribute it and/or modify
+@@ -57,32 +49,9 @@ along with GCC; see the file COPYING3.  If not see
+ #define SYMBOL_REF_SHORT_CALL_P(X)	\
+ 	((SYMBOL_REF_FLAGS (X) & SYMBOL_FLAG_SHORT_CALL) != 0)
+ 
+-#undef ASM_SPEC
+-#undef LINK_SPEC
+-#undef STARTFILE_SPEC
+-#undef ENDFILE_SPEC
+-#undef SIZE_TYPE
+-#undef PTRDIFF_TYPE
+-#undef WCHAR_TYPE
+-#undef WCHAR_TYPE_SIZE
+-#undef ASM_APP_ON
+-#undef ASM_APP_OFF
+-#undef CC1_SPEC
+-
+ /* Names to predefine in the preprocessor for this target machine.  */
+ #define TARGET_CPU_CPP_BUILTINS() arc_cpu_cpp_builtins (pfile)
+ 
+-#if DEFAULT_LIBC == LIBC_UCLIBC
+-
+-#define TARGET_OS_CPP_BUILTINS() \
+-  do \
+-    { \
+-      GNU_USER_TARGET_OS_CPP_BUILTINS (); \
+-    } \
+-  while (0)
+-
+-#endif /* DEFAULT_LIBC == LIBC_UCLIBC */
+-
+ /* Macros enabled by specific command line option.  FIXME: to be
+    deprecatd.  */
+ #define CPP_SPEC "\
+@@ -95,6 +64,7 @@ along with GCC; see the file COPYING3.  If not see
+ %{mlock:-D__Xlock} %{mswape:-D__Xswape} %{mrtsc:-D__Xrtsc} \
+ %{mcpu=nps400:-D__NPS400__}"
+ 
++#undef CC1_SPEC
+ #define CC1_SPEC "\
+ %{EB:%{EL:%emay not use both -EB and -EL}} \
+ %{EB:-mbig-endian} %{EL:-mlittle-endian} \
+@@ -104,71 +74,16 @@ extern const char *arc_cpu_to_as (int argc, const char **argv);
+ #define EXTRA_SPEC_FUNCTIONS			\
+   { "cpu_to_as", arc_cpu_to_as },
+ 
++#undef ASM_SPEC
+ #define ASM_SPEC  "%{mbig-endian|EB:-EB} %{EL} "			\
+   "%:cpu_to_as(%{mcpu=*:%*}) %{mspfp*} %{mdpfp*} %{mfpu=fpuda*:-mfpuda}"
+ 
+ #define OPTION_DEFAULT_SPECS						\
+   {"cpu", "%{!mcpu=*:%{!mARC*:%{!marc*:%{!mA7:%{!mA6:-mcpu=%(VALUE)}}}}}" }
+ 
+-#if DEFAULT_LIBC == LIBC_UCLIBC
+-/* Note that the default is to link against dynamic libraries, if they are
+-   available.  Override with -static.  */
+-#define LINK_SPEC "%{h*} \
+-		   %{static:-Bstatic} \
+-		   %{symbolic:-Bsymbolic} \
+-		   %{rdynamic:-export-dynamic}\
+-		   -dynamic-linker /lib/ld-uClibc.so.0 \
+-		   -X %{mbig-endian:-EB} \
+-		   %{EB} %{EL} \
+-		   %{marclinux*} \
+-		   %{!marclinux*: -marclinux} \
+-		   %{!z:-z max-page-size=0x2000 -z common-page-size=0x2000} \
+-		   %{shared:-shared}"
+-#else
+-#define LINK_SPEC "%{mbig-endian:-EB} %{EB} %{EL}"
+-#endif
+-
+-#if DEFAULT_LIBC != LIBC_UCLIBC
+-#define ARC_TLS_EXTRA_START_SPEC "crttls.o%s"
+-
+-#define EXTRA_SPECS \
+-  { "arc_tls_extra_start_spec", ARC_TLS_EXTRA_START_SPEC }, \
+-
+-#define STARTFILE_SPEC "%{pg|p:gcrt0.o%s}%{!pg:%{!p:crt0.o%s}} crti%O%s " \
+-  "%(arc_tls_extra_start_spec) crtbegin.o%s"
+-#else
+-#define STARTFILE_SPEC							\
+-  LINUX_OR_ANDROID_LD (GNU_USER_TARGET_STARTFILE_SPEC, ANDROID_STARTFILE_SPEC)
+-#endif
+-
+-#if DEFAULT_LIBC != LIBC_UCLIBC
+-#define ENDFILE_SPEC "crtend.o%s crtn%O%s"
+-#else
+-#define ENDFILE_SPEC							\
+-  LINUX_OR_ANDROID_LD (GNU_USER_TARGET_ENDFILE_SPEC, ANDROID_ENDFILE_SPEC)
+-#endif
+-
+-#if DEFAULT_LIBC == LIBC_UCLIBC
+-#undef LIB_SPEC
+-#define LIB_SPEC  \
+-  "%{pthread:-lpthread} \
+-   %{shared:-lc} \
+-   %{!shared:%{profile:-lc_p}%{!profile:-lc}}"
+-#define TARGET_ASM_FILE_END file_end_indicate_exec_stack
+-#else
+-#undef LIB_SPEC
+-#define LIB_SPEC "%{!shared:%{g*:-lg} -lc}"
+-#endif
+-
+ #ifndef DRIVER_ENDIAN_SELF_SPECS
+ #define DRIVER_ENDIAN_SELF_SPECS ""
+ #endif
+-#ifndef TARGET_SDATA_DEFAULT
+-#define TARGET_SDATA_DEFAULT 1
+-#endif
+-#ifndef TARGET_MMEDIUM_CALLS_DEFAULT
+-#define TARGET_MMEDIUM_CALLS_DEFAULT 0
+-#endif
+ 
+ #define DRIVER_SELF_SPECS DRIVER_ENDIAN_SELF_SPECS		   \
+   "%{mARC600|mA6: -mcpu=arc600 %<mARC600 %<mA6 %<mARC600}"	   \
+@@ -228,12 +143,6 @@ extern bool arc_arc601;
+ #define TARGET_HS (arc_archs)
+ #define TARGET_V2 (TARGET_EM || TARGET_HS)
+ 
+-#ifdef ARC_MULTILIB_CPU_DEFAULT
+-# ifndef MULTILIB_DEFAULTS
+-#  define MULTILIB_DEFAULTS { "mcpu=" ARC_MULTILIB_CPU_DEFAULT }
+-# endif
+-#endif
+-
+ #ifndef UNALIGNED_ACCESS_DEFAULT
+ #define UNALIGNED_ACCESS_DEFAULT 0
+ #endif
+@@ -316,15 +225,12 @@ if (GET_MODE_CLASS (MODE) == MODE_INT		\
+    `BIGGEST_ALIGNMENT' and `BIGGEST_FIELD_ALIGNMENT' to the
+    alignment) is COMPUTED.  It overrides alignment only if the field
+    alignment has not been set by the `__attribute__ ((aligned (N)))'
+-   construct.
+-*/
++   construct.  */
+ 
+ #define ADJUST_FIELD_ALIGN(FIELD, COMPUTED) \
+ (TYPE_MODE (strip_array_types (TREE_TYPE (FIELD))) == DFmode \
+  ? MIN ((COMPUTED), 32) : (COMPUTED))
+ 
+-
+-
+ /* No data type wants to be aligned rounder than this.  */
+ /* This is bigger than currently necessary for the ARC.  If 8 byte floats are
+    ever added it's not clear whether they'll need such alignment or not.  For
+@@ -375,13 +281,18 @@ if (GET_MODE_CLASS (MODE) == MODE_INT		\
+ /* Define this as 1 if `char' should by default be signed; else as 0.  */
+ #define DEFAULT_SIGNED_CHAR 0
+ 
++#undef SIZE_TYPE
+ #define SIZE_TYPE "long unsigned int"
++
++#undef PTRDIFF_TYPE
+ #define PTRDIFF_TYPE "long int"
++
++#undef WCHAR_TYPE
+ #define WCHAR_TYPE "int"
+-#define WCHAR_TYPE_SIZE 32
+ 
++#undef WCHAR_TYPE_SIZE
++#define WCHAR_TYPE_SIZE 32
+ 
+-/* ashwin : shifted from arc.c:102 */
+ #define PROGRAM_COUNTER_REGNO 63
+ 
+ /* Standard register usage.  */
+@@ -1164,10 +1075,12 @@ arc_select_cc_mode (OP, X, Y)
+ 
+ /* Output to assembler file text saying following lines
+    may contain character constants, extra white space, comments, etc.  */
++#undef ASM_APP_ON
+ #define ASM_APP_ON ""
+ 
+ /* Output to assembler file text saying following lines
+    no longer contain unusual constructs.  */
++#undef ASM_APP_OFF
+ #define ASM_APP_OFF ""
+ 
+ /* Globalizing directive for a label.  */
+@@ -1463,15 +1376,6 @@ extern int arc_return_address_regs[4];
+ 
+ /* Frame info.  */
+ 
+-/* Define this macro to 0 if your target supports DWARF 2 frame unwind
+-   information, but it does not yet work with exception handling.  */
+-/* N.B. the below test is valid in an #if, but not in a C expression.  */
+-#if DEFAULT_LIBC == LIBC_UCLIBC
+-#define DWARF2_UNWIND_INFO 1
+-#else
+-#define DWARF2_UNWIND_INFO 0
+-#endif
+-
+ #define EH_RETURN_DATA_REGNO(N)  ((N) < 2 ? (N) : INVALID_REGNUM)
+ 
+ #define EH_RETURN_STACKADJ_RTX   gen_rtx_REG (Pmode, 2)
+diff --git a/gcc/config/arc/big.h b/gcc/config/arc/big.h
+new file mode 100644
+index 000000000000..2ddad85551d4
+--- /dev/null
++++ b/gcc/config/arc/big.h
+@@ -0,0 +1,22 @@
++/* Definition of big endian ARC machine for GNU compiler.
++
++   Copyright (C) 2016 Free Software Foundation, Inc.
++
++This file is part of GCC.
++
++GCC is free software; you can redistribute it and/or modify
++it under the terms of the GNU General Public License as published by
++the Free Software Foundation; either version 3, or (at your option)
++any later version.
++
++GCC is distributed in the hope that it will be useful,
++but WITHOUT ANY WARRANTY; without even the implied warranty of
++MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
++GNU General Public License for more details.
++
++You should have received a copy of the GNU General Public License
++along with GCC; see the file COPYING3.  If not see
++<http://www.gnu.org/licenses/>.  */
++
++#undef DRIVER_ENDIAN_SELF_SPECS
++#define DRIVER_ENDIAN_SELF_SPECS "%{!EL:%{!mlittle-endian:-mbig-endian}}"
+diff --git a/gcc/config/arc/elf.h b/gcc/config/arc/elf.h
+new file mode 100644
+index 000000000000..96565e53115e
+--- /dev/null
++++ b/gcc/config/arc/elf.h
+@@ -0,0 +1,55 @@
++/* Target macros for arc*-elf targets.
++
++   Copyright (C) 2016 Free Software Foundation, Inc.
++
++This file is part of GCC.
++
++GCC is free software; you can redistribute it and/or modify
++it under the terms of the GNU General Public License as published by
++the Free Software Foundation; either version 3, or (at your option)
++any later version.
++
++GCC is distributed in the hope that it will be useful,
++but WITHOUT ANY WARRANTY; without even the implied warranty of
++MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
++GNU General Public License for more details.
++
++You should have received a copy of the GNU General Public License
++along with GCC; see the file COPYING3.  If not see
++<http://www.gnu.org/licenses/>.  */
++
++#undef DWARF2_UNWIND_INFO
++#define DWARF2_UNWIND_INFO 0
++
++#undef LINK_SPEC
++#define LINK_SPEC "%{mbig-endian:-EB} %{EB} %{EL}"
++
++#define ARC_TLS_EXTRA_START_SPEC "crttls.o%s"
++
++#define EXTRA_SPECS \
++  { "arc_tls_extra_start_spec", ARC_TLS_EXTRA_START_SPEC }, \
++
++#undef STARTFILE_SPEC
++#define STARTFILE_SPEC "%{pg|p:gcrt0.o%s}%{!pg:%{!p:crt0.o%s}} crti%O%s " \
++  "%(arc_tls_extra_start_spec) crtbegin.o%s"
++
++#undef ENDFILE_SPEC
++#define ENDFILE_SPEC "crtend.o%s crtn%O%s"
++
++/* Leave the linker script to choose the appropriate libraries.  */
++#undef LIB_SPEC
++#define LIB_SPEC ""
++
++/* SDATA default for elf.  */
++#undef TARGET_SDATA_DEFAULT
++#define TARGET_SDATA_DEFAULT 1
++
++/* We no medium calls.  */
++#undef TARGET_MMEDIUM_CALLS_DEFAULT
++#define TARGET_MMEDIUM_CALLS_DEFAULT 0
++
++#ifdef ARC_MULTILIB_CPU_DEFAULT
++# ifndef MULTILIB_DEFAULTS
++#  define MULTILIB_DEFAULTS { "mcpu=" ARC_MULTILIB_CPU_DEFAULT }
++# endif
++#endif
+diff --git a/gcc/config/arc/linux.h b/gcc/config/arc/linux.h
+new file mode 100644
+index 000000000000..e4a881fa940d
+--- /dev/null
++++ b/gcc/config/arc/linux.h
+@@ -0,0 +1,76 @@
++/* Target macros for arc*-*-linux targets.
++
++   Copyright (C) 2016 Free Software Foundation, Inc.
++
++This file is part of GCC.
++
++GCC is free software; you can redistribute it and/or modify
++it under the terms of the GNU General Public License as published by
++the Free Software Foundation; either version 3, or (at your option)
++any later version.
++
++GCC is distributed in the hope that it will be useful,
++but WITHOUT ANY WARRANTY; without even the implied warranty of
++MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
++GNU General Public License for more details.
++
++You should have received a copy of the GNU General Public License
++along with GCC; see the file COPYING3.  If not see
++<http://www.gnu.org/licenses/>.  */
++
++/* Enable DWARF 2 exceptions.  */
++#undef DWARF2_UNWIND_INFO
++#define DWARF2_UNWIND_INFO 1
++
++#define TARGET_OS_CPP_BUILTINS()		\
++  do						\
++    {						\
++      GNU_USER_TARGET_OS_CPP_BUILTINS ();	\
++    }						\
++  while (0)
++
++#define GLIBC_DYNAMIC_LINKER   "/lib/ld-linux.so.2"
++#define UCLIBC_DYNAMIC_LINKER  "/lib/ld-uClibc.so.0"
++
++/* Note that the default is to link against dynamic libraries, if they are
++   available.  Override with -static.  */
++#undef LINK_SPEC
++#define LINK_SPEC "%{h*} \
++  %{static:-Bstatic} \
++  %{shared:-shared} \
++  %{symbolic:-Bsymbolic} \
++  %{!static: \
++    %{rdynamic:-export-dynamic} \
++    %{!shared:-dynamic-linker " GNU_USER_DYNAMIC_LINKER "}} \
++  -X \
++  %{mbig-endian:-EB} %{EB} %{EL} \
++  %{!z:-z max-page-size=0x2000 -z common-page-size=0x2000} \
++  -marclinux"
++
++#undef STARTFILE_SPEC
++#define STARTFILE_SPEC							\
++  LINUX_OR_ANDROID_LD (GNU_USER_TARGET_STARTFILE_SPEC, ANDROID_STARTFILE_SPEC)
++
++#undef ENDFILE_SPEC
++#define ENDFILE_SPEC							\
++  LINUX_OR_ANDROID_LD (GNU_USER_TARGET_ENDFILE_SPEC, ANDROID_ENDFILE_SPEC)
++
++#undef LIB_SPEC
++#define LIB_SPEC  \
++  "%{pthread:-lpthread} \
++   %{shared:-lc} \
++   %{!shared:%{profile:-lc_p}%{!profile:-lc}}"
++
++#define TARGET_ASM_FILE_END file_end_indicate_exec_stack
++
++/* No SDATA default for linux.  */
++#undef TARGET_SDATA_DEFAULT
++#define TARGET_SDATA_DEFAULT 0
++
++/* We have medium calls.  */
++#undef TARGET_MMEDIUM_CALLS_DEFAULT
++#define TARGET_MMEDIUM_CALLS_DEFAULT 1
++
++/* We do not have any MULTILIB_OPTIONS specified, so there are no
++   MULTILIB_DEFAULTS.  */
++#undef  MULTILIB_DEFAULTS
+diff --git a/gcc/config/arc/t-uClibc b/gcc/config/arc/t-uClibc
+deleted file mode 100644
+index 11e81f1ee5ef..000000000000
+--- a/gcc/config/arc/t-uClibc
++++ /dev/null
+@@ -1,20 +0,0 @@
+-# GCC Makefile fragment for Synopsys DesignWare ARC with uClibc
+-
+-# Copyright (C) 2007-2016 Free Software Foundation, Inc.
+-
+-# This file is part of GCC.
+-
+-# GCC is free software; you can redistribute it and/or modify it under the
+-# terms of the GNU General Public License as published by the Free Software
+-# Foundation; either version 3, or (at your option) any later version.
+-
+-# GCC is distributed in the hope that it will be useful, but WITHOUT ANY
+-# WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
+-# FOR A PARTICULAR PURPOSE.  See the GNU General Public License for more
+-# details.
+-
+-# You should have received a copy of the GNU General Public License along
+-# with GCC; see the file COPYING3.  If not see
+-# <http://www.gnu.org/licenses/>.
+-
+-MULTILIB_EXTRA_OPTS = mno-sdata
+-- 
+2.7.4
+
diff --git a/toolchain/gcc/patches/6.3.0/0041-ARC-Configure-script-to-allow-non-uclibc-based-tripl.patch b/toolchain/gcc/patches/6.3.0/0041-ARC-Configure-script-to-allow-non-uclibc-based-tripl.patch
new file mode 100644
index 0000000..c03e541
--- /dev/null
+++ b/toolchain/gcc/patches/6.3.0/0041-ARC-Configure-script-to-allow-non-uclibc-based-tripl.patch
@@ -0,0 +1,49 @@
+From 5a6e68beb138a8a30dfae633ceb6c24c4663d4e6 Mon Sep 17 00:00:00 2001
+From: Claudiu Zissulescu <claziss at synopsys.com>
+Date: Fri, 29 Jul 2016 16:04:33 +0200
+Subject: [PATCH 41/89] [ARC] Configure script to allow non uclibc based
+ triplets
+
+gcc/
+2016-07-28  Vineet Gupta <vgupta at synopsys.com>
+
+	* config.gcc (arc*-*-linux): Remove uclibc from arc target spec.
+
+libgcc/
+2016-07-28  Vineet Gupta <vgupta at synopsys.com>
+
+	* config.host (arc*-*-linux): Remove uclibc from arc target spec.
+---
+ gcc/config.gcc     | 2 +-
+ libgcc/config.host | 2 +-
+ 2 files changed, 2 insertions(+), 2 deletions(-)
+
+diff --git a/gcc/config.gcc b/gcc/config.gcc
+index 972f8f3ac130..a3cfcc2aa2fa 100644
+--- a/gcc/config.gcc
++++ b/gcc/config.gcc
+@@ -1023,7 +1023,7 @@ arc*-*-elf*)
+ 	big*)	tm_file="arc/big.h ${tm_file}"
+ 	esac
+ 	;;
+-arc*-*-linux-uclibc*)
++arc*-*-linux*)
+ 	tm_file="arc/arc-arch.h dbxelf.h elfos.h gnu-user.h linux.h linux-android.h glibc-stdint.h arc/linux.h ${tm_file}"
+ 	tmake_file="${tmake_file} arc/t-arc"
+ 	extra_gcc_objs="driver-arc.o"
+diff --git a/libgcc/config.host b/libgcc/config.host
+index 035d38d03713..092b00268cc7 100644
+--- a/libgcc/config.host
++++ b/libgcc/config.host
+@@ -369,7 +369,7 @@ arc*-*-elf*)
+ 	extra_parts="crti.o crtn.o crtend.o crtbegin.o crtendS.o crtbeginS.o"
+ 	extra_parts="$extra_parts crttls.o"
+ 	;;
+-arc*-*-linux-uclibc*)
++arc*-*-linux*)
+ 	tmake_file="${tmake_file} t-slibgcc-libgcc t-slibgcc-nolc-override arc/t-arc-uClibc arc/t-arc"
+ 	extra_parts="$extra_parts crti.o crtn.o"
+ 	extra_parts="$extra_parts crttls.o"
+-- 
+2.7.4
+
diff --git a/toolchain/gcc/patches/6.3.0/0042-ARC-Fix-conditional-move-contstraint.patch b/toolchain/gcc/patches/6.3.0/0042-ARC-Fix-conditional-move-contstraint.patch
new file mode 100644
index 0000000..6589664
--- /dev/null
+++ b/toolchain/gcc/patches/6.3.0/0042-ARC-Fix-conditional-move-contstraint.patch
@@ -0,0 +1,32 @@
+From 7cf41ca830af0de2cc7c0222d96b40921c02ffb1 Mon Sep 17 00:00:00 2001
+From: Claudiu Zissulescu <claziss at synopsys.com>
+Date: Mon, 22 Aug 2016 19:58:25 +0200
+Subject: [PATCH 42/89] [ARC] Fix conditional move contstraint
+
+Move pattern (movsi_insn) allows predicated instructions to be
+instructions which can hold all registers.  However, the conditional
+variant doesn't.  This patch fixes this problem.
+
+2016-08-22  Claudiu Zissulescu  <claziss at synopsys.com>
+
+	* config/arc/arc.md (movsi_cond_exec): Update constraint.
+---
+ gcc/config/arc/arc.md | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+diff --git a/gcc/config/arc/arc.md b/gcc/config/arc/arc.md
+index d87174a7f321..607c6e6614e6 100644
+--- a/gcc/config/arc/arc.md
++++ b/gcc/config/arc/arc.md
+@@ -3603,7 +3603,7 @@
+      (match_operator 3 "proper_comparison_operator"
+        [(match_operand 2 "cc_register" "Rcc,Rcc") (const_int 0)])
+      (set (match_operand:SI 0 "dest_reg_operand" "=w,w")
+-	  (match_operand:SI 1 "nonmemory_operand" "Lc,?Cal")))]
++	  (match_operand:SI 1 "nonmemory_operand" "LRac,?Cal")))]
+   ""
+   "mov.%d3 %0,%S1"
+   [(set_attr "type" "cmove")
+-- 
+2.7.4
+
diff --git a/toolchain/gcc/patches/6.3.0/0043-Fix-tst_bitfield_tst-pattern.patch b/toolchain/gcc/patches/6.3.0/0043-Fix-tst_bitfield_tst-pattern.patch
new file mode 100644
index 0000000..f8730d9
--- /dev/null
+++ b/toolchain/gcc/patches/6.3.0/0043-Fix-tst_bitfield_tst-pattern.patch
@@ -0,0 +1,66 @@
+From a4c30f398ad4feb3ec5133397a2e93b886a263ae Mon Sep 17 00:00:00 2001
+From: Claudiu Zissulescu <claziss at synopsys.com>
+Date: Wed, 7 Sep 2016 13:04:32 +0200
+Subject: [PATCH 43/89] Fix tst_bitfield_tst pattern.
+
+gcc/
+2016-09-07  Claudiu Zissulescu  <claziss at synopsys.com>
+
+	* config/arc/arc.md (*tst_bitfield_tst): Fix pattern.
+	* testsuite/gcc.target/arc/bitfield.c: New file.
+---
+ gcc/config/arc/arc.md                   |  2 +-
+ gcc/testsuite/gcc.target/arc/bitfield.c | 28 ++++++++++++++++++++++++++++
+ 2 files changed, 29 insertions(+), 1 deletion(-)
+ create mode 100755 gcc/testsuite/gcc.target/arc/bitfield.c
+
+diff --git a/gcc/config/arc/arc.md b/gcc/config/arc/arc.md
+index 607c6e6614e6..a7ffed3f0c52 100644
+--- a/gcc/config/arc/arc.md
++++ b/gcc/config/arc/arc.md
+@@ -888,7 +888,7 @@
+    && (INTVAL (operands[3]) + INTVAL (operands[2]) <= 11
+        || (INTVAL (operands[3]) <= 11
+ 	   && INTVAL (operands[3]) + INTVAL (operands[2]) == 32))"
+-  "tst %1,(1<<%2)-1<<%3"
++  "tst %1,((1<<%2)-1)<<%3"
+   [(set_attr "type" "compare")
+    (set_attr "cond" "set_zn")
+    (set_attr "length" "4")])
+diff --git a/gcc/testsuite/gcc.target/arc/bitfield.c b/gcc/testsuite/gcc.target/arc/bitfield.c
+new file mode 100755
+index 000000000000..187cd1ddb5fe
+--- /dev/null
++++ b/gcc/testsuite/gcc.target/arc/bitfield.c
+@@ -0,0 +1,28 @@
++/* { dg-do run } */
++/* { dg-options "-O2" } */
++
++#include <stdlib.h>
++
++struct ubifs_budget_req {
++  unsigned int fast:7;
++  unsigned int new_ino_d:13;
++};
++
++int printf(const char *format, ...);
++
++void __attribute__ ((noinline))
++fff(struct ubifs_budget_req *req)
++{
++  if (req->new_ino_d & 7)
++    abort ();
++}
++
++int main (void)
++{
++  struct ubifs_budget_req req = {
++    .fast = 8,
++    .new_ino_d = 0,
++  };
++  fff(&req);
++  return 0;
++}
+-- 
+2.7.4
+
diff --git a/toolchain/gcc/patches/6.3.0/0044-ARC-Prohibit-negative-PIC-constants.patch b/toolchain/gcc/patches/6.3.0/0044-ARC-Prohibit-negative-PIC-constants.patch
new file mode 100644
index 0000000..e952b16
--- /dev/null
+++ b/toolchain/gcc/patches/6.3.0/0044-ARC-Prohibit-negative-PIC-constants.patch
@@ -0,0 +1,105 @@
+From b0d9ad169e43483872e95a3a6901407b565bbc74 Mon Sep 17 00:00:00 2001
+From: Claudiu Zissulescu <claziss at synopsys.com>
+Date: Thu, 15 Sep 2016 15:06:24 +0200
+Subject: [PATCH 44/89] [ARC] Prohibit negative PIC constants.
+
+Avoid to generate a PIC constant which uses neg code.
+
+gcc/
+2016-09-15  Claudiu Zissulescu  <claziss at synopsys.com>
+
+	* testsuite/gcc.target/arc/pr9000674901.c: New file.
+	* config/arc/arc.c (arc_legitimate_constant_p): Avoid negative PIC
+	constants.
+---
+ gcc/config/arc/arc.c                        |  8 ++++
+ gcc/testsuite/gcc.target/arc/pr9000674901.c | 58 +++++++++++++++++++++++++++++
+ 2 files changed, 66 insertions(+)
+ create mode 100644 gcc/testsuite/gcc.target/arc/pr9000674901.c
+
+diff --git a/gcc/config/arc/arc.c b/gcc/config/arc/arc.c
+index 4e478131da35..2135bf0f8cd2 100644
+--- a/gcc/config/arc/arc.c
++++ b/gcc/config/arc/arc.c
+@@ -5461,6 +5461,14 @@ arc_legitimate_constant_p (machine_mode mode, rtx x)
+ 	  x = XEXP (x, 0);
+ 	}
+ 
++      if (GET_CODE (x) == NEG)
++	{
++	  /* Assembler does not understand -(@label at gotoff).  Also, we
++	     do not print such pic address constant.  */
++	  if (GET_CODE (XEXP (x, 0)) == UNSPEC)
++	    return false;
++	}
++
+       /* Only some unspecs are valid as "constants".  */
+       if (GET_CODE (x) == UNSPEC)
+ 	switch (XINT (x, 1))
+diff --git a/gcc/testsuite/gcc.target/arc/pr9000674901.c b/gcc/testsuite/gcc.target/arc/pr9000674901.c
+new file mode 100644
+index 000000000000..2a15c1c1478e
+--- /dev/null
++++ b/gcc/testsuite/gcc.target/arc/pr9000674901.c
+@@ -0,0 +1,58 @@
++/* { dg-do compile } */
++/* { dg-skip-if "" { ! { clmcpu } } } */
++/* { dg-options "-mcpu=arc700 -O2 -fpic" } */
++
++/* Test if the compiler generates a constant address having that uses
++   a neg keyword on the pic unspec.  */
++
++typedef unsigned int uint32_t;
++typedef unsigned char uint8_t;
++typedef unsigned short int uint16_t;
++typedef unsigned long long int uint64_t;
++
++enum type {
++ t_undef = 0x01,
++ t_group = 0x02,
++ t_partition = 0x04,
++ t_spare = 0x08,
++ t_linear = 0x10,
++ t_raid0 = 0x20,
++ t_raid1 = 0x40,
++ t_raid4 = 0x80,
++ t_raid5_ls = 0x100,
++ t_raid5_rs = 0x200,
++ t_raid5_la = 0x400,
++ t_raid5_ra = 0x800,
++ t_raid6 = 0x1000,
++};
++
++struct raid_set {
++  enum type type;
++};
++
++void
++_find_factors (struct raid_set *rs, uint8_t * div, uint8_t * sub)
++{
++  struct factors {
++    const uint8_t level;
++    const uint8_t div, sub;
++  };
++  static struct factors factors[] = {
++    {0, 1, 0},
++    {1, 2, 0},
++    {2, 2, 0},
++    {5, 1, 1},
++  };
++  struct factors *f = (factors + (sizeof (factors) / sizeof (*factors)));
++
++  while (f-- > factors) {
++    if (rs->type == f->level) {
++      *div = f->div;
++      *sub = f->sub;
++      return;
++    }
++  }
++
++  *div = 1;
++  *sub = 0;
++}
+-- 
+2.7.4
+
diff --git a/toolchain/gcc/patches/6.3.0/0045-ARC-Handle-complex-PIC-move-patterns.patch b/toolchain/gcc/patches/6.3.0/0045-ARC-Handle-complex-PIC-move-patterns.patch
new file mode 100644
index 0000000..9aa1f07
--- /dev/null
+++ b/toolchain/gcc/patches/6.3.0/0045-ARC-Handle-complex-PIC-move-patterns.patch
@@ -0,0 +1,120 @@
+From 17cba35c2d8f0a42b732e6d3b33d5ce608f2a3f3 Mon Sep 17 00:00:00 2001
+From: Claudiu Zissulescu <claziss at synopsys.com>
+Date: Fri, 16 Sep 2016 14:13:59 +0200
+Subject: [PATCH 45/89] [ARC] Handle complex PIC move patterns.
+
+fwprop step is placing in the REG_EQUIV notes constant pic unspecs
+expressions.  Then, loop may use these notes for optimizations
+rezulting in complex patterns that are not supported by the current
+implementation.
+
+The patch adds handling of complex PIC addresses having MINUS or UNARY
+operations.
+
+gcc/
+2016-09-16  Claudiu Zissulescu  <claziss at synopsys.com>
+
+	* config/arc/arc.c (arc_legitimize_pic_address): Handle PIC
+	expressions with MINUS and UNARY ops.
+	* testsuite/gcc.target/arc/pr9001090948.c: New file.
+---
+ gcc/config/arc/arc.c                        | 49 ++++++++++++++++++++++++++++-
+ gcc/testsuite/gcc.target/arc/pr9001090948.c | 25 +++++++++++++++
+ 2 files changed, 73 insertions(+), 1 deletion(-)
+ create mode 100644 gcc/testsuite/gcc.target/arc/pr9001090948.c
+
+diff --git a/gcc/config/arc/arc.c b/gcc/config/arc/arc.c
+index 2135bf0f8cd2..e8a157aab33d 100644
+--- a/gcc/config/arc/arc.c
++++ b/gcc/config/arc/arc.c
+@@ -5028,8 +5028,55 @@ arc_legitimize_pic_address (rtx orig, rtx oldx)
+ 	      /* Check that the unspec is one of the ones we generate?  */
+ 	      return orig;
+ 	    }
++	  /* fwprop is placing in the REG_EQUIV notes constant pic
++	     unspecs expressions.  Then, loop may use these notes for
++	     optimizations rezulting in complex patterns that are not
++	     supported by the current implementation. The following
++	     two if-cases are simplifying the complex patters in
++	     simpler ones.  */
++	  else if (GET_CODE (addr) == MINUS)
++	    {
++	      rtx op0 = XEXP (addr, 0);
++	      rtx op1 = XEXP (addr, 1);
++	      gcc_assert (oldx);
++	      gcc_assert (GET_CODE (op1) == UNSPEC);
++
++	      emit_move_insn (oldx,
++			      gen_rtx_CONST (SImode,
++					     arc_legitimize_pic_address (op1,
++									 NULL_RTX)));
++	      emit_insn (gen_rtx_SET (oldx, gen_rtx_MINUS (SImode, op0, oldx)));
++	      return oldx;
++
++	    }
++	  else if (GET_CODE (addr) != PLUS)
++	    {
++	      rtx tmp = XEXP (addr, 0);
++	      enum rtx_code code = GET_CODE (addr);
++
++	      /* It only works for UNARY operations.  */
++	      gcc_assert (UNARY_P (addr));
++	      gcc_assert (GET_CODE (tmp) == UNSPEC);
++	      gcc_assert (oldx);
++
++	      emit_move_insn
++		(oldx,
++		 gen_rtx_CONST (SImode,
++				arc_legitimize_pic_address (tmp,
++							    NULL_RTX)));
++
++	      emit_insn (gen_rtx_SET (oldx,
++				      gen_rtx_fmt_ee (code, SImode,
++						      oldx, const0_rtx)));
++
++	      return oldx;
++	    }
+ 	  else
+-	    gcc_assert (GET_CODE (addr) == PLUS);
++	    {
++	      gcc_assert (GET_CODE (addr) == PLUS);
++	      if (GET_CODE (XEXP (addr, 0)) == UNSPEC)
++		return orig;
++	    }
+ 	}
+ 
+       if (GET_CODE (addr) == PLUS)
+diff --git a/gcc/testsuite/gcc.target/arc/pr9001090948.c b/gcc/testsuite/gcc.target/arc/pr9001090948.c
+new file mode 100644
+index 000000000000..103f4aee7ec5
+--- /dev/null
++++ b/gcc/testsuite/gcc.target/arc/pr9001090948.c
+@@ -0,0 +1,25 @@
++/* { dg-do compile } */
++/* { dg-skip-if "ARC600 doesn't support pic" { arc6xx } } */
++/* { dg-options "-Os -fPIC" } */
++#include <stdio.h>
++#include <string.h>
++
++char *
++strip_trail (const char str[], size_t n)
++{
++  static char buf[1025];
++  int j;
++
++  strncpy (buf, str, n);
++  buf[n] = '\0';
++
++  for (j = strlen (buf) - 1; j >= 0; j--)
++    {
++      if (buf[j] != ' ')
++        break;
++
++      buf[j] = '\0';
++    }
++
++  return buf;
++}
+-- 
+2.7.4
+
diff --git a/toolchain/gcc/patches/6.3.0/0046-ARC-Add-code-density-instructions.patch b/toolchain/gcc/patches/6.3.0/0046-ARC-Add-code-density-instructions.patch
new file mode 100644
index 0000000..9f6d36f
--- /dev/null
+++ b/toolchain/gcc/patches/6.3.0/0046-ARC-Add-code-density-instructions.patch
@@ -0,0 +1,300 @@
+From 10a2b73d90a8a365037431ce8e5edb86b7d86d0b Mon Sep 17 00:00:00 2001
+From: Claudiu Zissulescu <claziss at synopsys.com>
+Date: Fri, 16 Sep 2016 17:46:56 +0200
+Subject: [PATCH 46/89] [ARC] Add code density instructions.
+
+gcc/
+2016-09-16  Claudiu Zissulescu  <claziss at synopsys.com>
+
+	* config/arc/arc.c (arc_output_addsi): Emit code density adds.
+	* config/arc/arc.md (cpu_facility): Add cd variant.
+	(*movqi_insn): Add code density variant.
+	(*movhi_insn): Likewise.
+	(*movqi_insn): Likewise.
+	(*addsi3_mixed): Likewise.
+	(subsi3_insn): Likewise.
+---
+ gcc/config/arc/arc.c  |  11 +++++
+ gcc/config/arc/arc.md | 130 ++++++++++++++++++++++++++++----------------------
+ 2 files changed, 84 insertions(+), 57 deletions(-)
+
+diff --git a/gcc/config/arc/arc.c b/gcc/config/arc/arc.c
+index e8a157aab33d..498bdfd422dd 100644
+--- a/gcc/config/arc/arc.c
++++ b/gcc/config/arc/arc.c
+@@ -7396,6 +7396,17 @@ arc_output_addsi (rtx *operands, bool cond_p, bool output_p)
+ 	  || (REGNO (operands[0]) == STACK_POINTER_REGNUM
+ 	      && match && !(neg_intval & ~124)))
+ 	ADDSI_OUTPUT1 ("sub%? %0,%1,%n2");
++
++      if (REG_P(operands[0]) && REG_P(operands[1])
++	  && (REGNO(operands[0]) <= 31) && (REGNO(operands[0]) == REGNO(operands[1]))
++	  && CONST_INT_P (operands[2]) && ( (intval>= -1) && (intval <= 6)))
++	ADDSI_OUTPUT1 ("add%? %0,%1,%2");
++
++      if (TARGET_CODE_DENSITY && REG_P(operands[0]) && REG_P(operands[1])
++	  && ((REGNO(operands[0]) == 0) || (REGNO(operands[0]) == 1))
++	  && satisfies_constraint_Rcq (operands[1])
++	  && satisfies_constraint_L (operands[2]))
++	ADDSI_OUTPUT1 ("add%? %0,%1,%2 ;3");
+     }
+ 
+   /* Now try to emit a 32 bit insn without long immediate.  */
+diff --git a/gcc/config/arc/arc.md b/gcc/config/arc/arc.md
+index a7ffed3f0c52..2b239d7268f5 100644
+--- a/gcc/config/arc/arc.md
++++ b/gcc/config/arc/arc.md
+@@ -261,7 +261,7 @@
+ 		     - get_attr_length (insn)")))
+ 
+ ; for ARCv2 we need to disable/enable different instruction alternatives
+-(define_attr "cpu_facility" "std,av1,av2,fpx"
++(define_attr "cpu_facility" "std,av1,av2,fpx,cd"
+   (const_string "std"))
+ 
+ ; We should consider all the instructions enabled until otherwise
+@@ -277,6 +277,11 @@
+ 	 (and (eq_attr "cpu_facility" "fpx")
+ 	      (match_test "TARGET_FP_DP_AX"))
+ 	 (const_string "no")
++
++	 (and (eq_attr "cpu_facility" "cd")
++	      (not (and (match_test "TARGET_V2")
++			(match_test "TARGET_CODE_DENSITY"))))
++	 (const_string "no")
+ 	 ]
+ 	(const_string "yes")))
+ 
+@@ -611,8 +616,8 @@
+ ; The iscompact attribute allows the epilogue expander to know for which
+ ; insns it should lengthen the return insn.
+ (define_insn "*movqi_insn"
+-  [(set (match_operand:QI 0 "move_dest_operand" "=Rcq,Rcq#q,    w,   h, w,w,???w, w,Rcq,  S,!*x,  r,r, Ucm,m,???m")
+-	(match_operand:QI 1 "move_src_operand"  "  cL,   cP,Rcq#q,hCm1,cL,I,?Rac,?i,  T,Rcq,Usd,Ucm,m,?Rac,c,?Rac"))]
++  [(set (match_operand:QI 0 "move_dest_operand" "=Rcq,Rcq#q,    w,Rcq#q,   h, w,w,???w,h, w,Rcq,  S,!*x,  r,r, Ucm,m,???m,Usc")
++	(match_operand:QI 1 "move_src_operand"  "  cL,   cP,Rcq#q,    P,hCm1,cL,I,?Rac,i,?i,  T,Rcq,Usd,Ucm,m,?Rac,c,?Rac,Cm3"))]
+   "register_operand (operands[0], QImode)
+    || register_operand (operands[1], QImode)"
+   "@
+@@ -620,6 +625,8 @@
+    mov%? %0,%1%&
+    mov%? %0,%1%&
+    mov%? %0,%1%&
++   mov%? %0,%1%&
++   mov%? %0,%1
+    mov%? %0,%1
+    mov%? %0,%1
+    mov%? %0,%1
+@@ -631,11 +638,12 @@
+    ldb%U1%V1 %0,%1
+    xstb%U0 %1,%0
+    stb%U0%V0 %1,%0
++   stb%U0%V0 %1,%0
+    stb%U0%V0 %1,%0"
+-  [(set_attr "type" "move,move,move,move,move,move,move,move,load,store,load,load,load,store,store,store")
+-   (set_attr "iscompact" "maybe,maybe,maybe,true,false,false,false,false,true,true,true,false,false,false,false,false")
+-   (set_attr "predicable" "yes,no,yes,no,yes,no,yes,yes,no,no,no,no,no,no,no,no")
+-   (set_attr "cpu_facility" "*,*,av1,av2,*,*,*,*,*,*,*,*,*,*,*,*")])
++  [(set_attr "type" "move,move,move,move,move,move,move,move,move,move,load,store,load,load,load,store,store,store,store")
++   (set_attr "iscompact" "maybe,maybe,maybe,true,true,false,false,false,maybe_limm,false,true,true,true,false,false,false,false,false,false")
++   (set_attr "predicable" "yes,no,yes,no,no,yes,no,yes,yes,yes,no,no,no,no,no,no,no,no,no")
++   (set_attr "cpu_facility" "av1,av1,av1,av2,av2,*,*,*,*,*,*,*,*,*,*,*,*,*,*")])
+ 
+ (define_expand "movhi"
+   [(set (match_operand:HI 0 "move_dest_operand" "")
+@@ -644,8 +652,8 @@
+   "if (prepare_move_operands (operands, HImode)) DONE;")
+ 
+ (define_insn "*movhi_insn"
+-  [(set (match_operand:HI 0 "move_dest_operand" "=Rcq,Rcq#q,    w,   h, w,w,???w,Rcq#q, w,Rcq,  S,  r,r, Ucm,m,???m,VUsc,VUsc")
+-	(match_operand:HI 1 "move_src_operand" "   cL,   cP,Rcq#q,hCm1,cL,I,?Rac,   ?i,?i,  T,Rcq,Ucm,m,?Rac,c,?Rac, Cm3,i"))]
++  [(set (match_operand:HI 0 "move_dest_operand" "=Rcq,Rcq#q,    w,Rcq#q,   h, w,w,???w,Rcq#q,h, w,Rcq,  S,  r,r, Ucm,m,???m,VUsc,VUsc")
++	(match_operand:HI 1 "move_src_operand" "   cL,   cP,Rcq#q,    P,hCm1,cL,I,?Rac,    i,i,?i,  T,Rcq,Ucm,m,?Rac,c,?Rac, Cm3,i"))]
+   "register_operand (operands[0], HImode)
+    || register_operand (operands[1], HImode)
+    || (CONSTANT_P (operands[1])
+@@ -658,11 +666,13 @@
+    mov%? %0,%1%&
+    mov%? %0,%1%&
+    mov%? %0,%1%&
++   mov%? %0,%1%&
+    mov%? %0,%1
+    mov%? %0,%1
+    mov%? %0,%1
+    mov%? %0,%S1%&
+    mov%? %0,%S1
++   mov%? %0,%S1
+    ld%_%? %0,%1%&
+    st%_%? %1,%0%&
+    xld%_%U1 %0,%1
+@@ -672,10 +682,10 @@
+    st%_%U0%V0 %1,%0
+    st%_%U0%V0 %S1,%0
+    st%_%U0%V0 %S1,%0"
+-  [(set_attr "type" "move,move,move,move,move,move,move,move,move,load,store,load,load,store,store,store,store,store")
+-   (set_attr "iscompact" "maybe,maybe,maybe,true,false,false,false,maybe_limm,false,true,true,false,false,false,false,false,false,false")
+-   (set_attr "predicable" "yes,no,yes,no,yes,no,yes,yes,yes,no,no,no,no,no,no,no,no,no")
+-   (set_attr "cpu_facility" "*,*,av1,av2,*,*,*,*,*,*,*,*,*,*,*,*,av2,*")])
++  [(set_attr "type" "move,move,move,move,move,move,move,move,move,move,move,load,store,load,load,store,store,store,store,store")
++   (set_attr "iscompact" "maybe,maybe,maybe,true,true,false,false,false,maybe_limm,maybe_limm,false,true,true,false,false,false,false,false,false,false")
++   (set_attr "predicable" "yes,no,yes,no,no,yes,no,yes,yes,yes,yes,no,no,no,no,no,no,no,no,no")
++   (set_attr "cpu_facility" "av1,av1,av1,av2,av2,*,*,*,*,*,*,*,*,*,*,*,*,*,av2,*")])
+ 
+ (define_expand "movsi"
+   [(set (match_operand:SI 0 "move_dest_operand" "")
+@@ -693,9 +703,9 @@
+ ; the iscompact attribute allows the epilogue expander to know for which
+ ; insns it should lengthen the return insn.
+ ; N.B. operand 1 of alternative 7 expands into pcl,symbol at gotpc .
+-(define_insn "*movsi_insn"                      ;   0     1     2     3  4 5   6   7   8   9   10  11  12    13   14  15  16     17     18 19   20    21    22 23 24    25 26  27   28   29
+-  [(set (match_operand:SI 0 "move_dest_operand" "=Rcq,Rcq#q,    w,    h, w,w,  w,  w,  w,  w,???w, ?w,  w,Rcq#q,   w,Rcq,  S,   Us<,RcqRck,!*x,  r,!*Rsd,!*Rcd,r,Ucm,  Usd,m,???m,VUsc,VUsc")
+-	(match_operand:SI 1 "move_src_operand"  "  cL,   cP,Rcq#q,hPCm1,cL,I,Crr,Clo,Chi,Cbi,?Rac,Cpc,Clb, ?Cal,?Cal,  T,Rcq,RcqRck,   Us>,Usd,Ucm,  Usd,  Ucd,m,  w,!*Rzd,c,?Rac, Cm3, C32"))]
++(define_insn "*movsi_insn"                      ;   0     1     2     3    4  5 6   7   8   9   10  11  12  13    14  15   16  17  18     19     20  21  22    23    24 25 26    27 28  29   30   31
++  [(set (match_operand:SI 0 "move_dest_operand" "=Rcq,Rcq#q,    w,Rcq#q,   h, w,w,  w,  w,  w,  w,???w, ?w,  w,Rcq#q,  h,   w,Rcq,  S,   Us<,RcqRck,!*x,  r,!*Rsd,!*Rcd,r,Ucm,  Usd,m,???m,VUsc,VUsc")
++	(match_operand:SI 1 "move_src_operand"  "  cL,   cP,Rcq#q,    P,hCm1,cL,I,Crr,Clo,Chi,Cbi,?Rac,Cpc,Clb, ?Cal,Cal,?Cal,  T,Rcq,RcqRck,   Us>,Usd,Ucm,  Usd,  Ucd,m,  w,!*Rzd,c,?Rac, Cm3, C32"))]
+   "register_operand (operands[0], SImode)
+    || register_operand (operands[1], SImode)
+    || (CONSTANT_P (operands[1])
+@@ -708,39 +718,42 @@
+    mov%? %0,%1%&	;1
+    mov%? %0,%1%&	;2
+    mov%? %0,%1%&	;3
+-   mov%? %0,%1		;4
++   mov%? %0,%1%&	;4
+    mov%? %0,%1		;5
+-   ror %0,((%1*2+1) & 0x3f) ;6
+-   movl.cl %0,%1	;7
+-   movh.cl %0,%L1>>16   ;8
+-   * return INTVAL (operands[1]) & 0xffffff ? \"movbi.cl %0,%1 >> %p1,%p1,8;8\" : \"movbi.cl %0,%L1 >> 24,24,8;9\";
+-   mov%? %0,%1		;10
+-   add %0,%S1		;11
+-   add %0,pcl,%1 at pcl    ;12
+-   mov%? %0,%S1%&	;13
+-   mov%? %0,%S1		;14
+-   ld%? %0,%1%&		;15
+-   st%? %1,%0%&		;16
++   mov%? %0,%1		;6
++   ror %0,((%1*2+1) & 0x3f) ;7
++   movl.cl %0,%1	;8
++   movh.cl %0,%L1>>16   ;9
++   * return INTVAL (operands[1]) & 0xffffff ? \"movbi.cl %0,%1 >> %p1,%p1,8;10\" : \"movbi.cl %0,%L1 >> 24,24,8;10\";
++   mov%? %0,%1		;11
++   add %0,%S1		;12
++   add %0,pcl,%1 at pcl    ;13
++   mov%? %0,%S1%&	;14
++   mov%? %0,%S1		;15
++   mov%? %0,%S1		;16
++   ld%? %0,%1%&		;17
++   st%? %1,%0%&		;18
+    * return arc_short_long (insn, \"push%? %1%&\", \"st%U0 %1,%0%&\");
+    * return arc_short_long (insn, \"pop%? %0%&\",  \"ld%U1 %0,%1%&\");
+-   ld%? %0,%1%&		;19
+-   xld%U1 %0,%1		;20
+    ld%? %0,%1%&		;21
+-   ld%? %0,%1%&		;22
+-   ld%U1%V1 %0,%1	;23
+-   xst%U0 %1,%0		;24
+-   st%? %1,%0%&		;25
+-   st%U0%V0 %1,%0	;26
+-   st%U0%V0 %1,%0	;27
++   xld%U1 %0,%1		;22
++   ld%? %0,%1%&		;23
++   ld%? %0,%1%&		;24
++   ld%U1%V1 %0,%1	;25
++   xst%U0 %1,%0		;26
++   st%? %1,%0%&		;27
+    st%U0%V0 %1,%0	;28
+-   st%U0%V0 %S1,%0	;29"
+-  [(set_attr "type" "move,move,move,move,move,move,two_cycle_core,shift,shift,shift,move,binary,binary,move,move,load,store,store,load,load,load,load,load,load,store,store,store,store,store,store")
+-   (set_attr "iscompact" "maybe,maybe,maybe,false,false,false,false,false,false,false,false,false,maybe_limm,false,true,true,true,true,true,false,false,false,false,false,false,false,false,false,false,false")
++   st%U0%V0 %1,%0	;29
++   st%U0%V0 %1,%0	;30
++   st%U0%V0 %S1,%0	;31"
++   ;                         0     1     2     3    4    5      6       7           8     9    10     11    12    13           14        15    16   17    18    19   20    21    22   23  24    25    26    27    28    29   30   31
++  [(set_attr "type"       "move, move, move,move,move, move, move,two_cycle_core,shift,shift,shift, move,binary,binary,      move,      move, move,load,store,store,load,load, load,load,load, load,store,store,store,store,store,store")
++   (set_attr "iscompact" "maybe,maybe,maybe,true,true,false,false,         false,false,false,false,false, false, false,maybe_limm,maybe_limm,false,true, true, true,true,true,false,true,true,false,false, true,false,false,false,false")
+    ; Use default length for iscompact to allow for COND_EXEC.  But set length
+    ; of Crr to 4.
+-   (set_attr "length" "*,*,*,*,4,4,4,4,4,4,4,8,8,*,8,*,*,*,*,*,4,*,4,*,*,*,*,*,4,8")
+-   (set_attr "predicable" "yes,no,yes,no,yes,no,no,no,no,no,yes,no,no,yes,yes,no,no,no,no,no,no,no,no,no,no,no,no,no,no,no")
+-   (set_attr "cpu_facility" "av1,av1,av1,av2,*,*,*,*,*,*,*,*,*,*,*,*,*,*,*,*,*,av2,av2,*,*,av2,*,*,av2,*")])
++   (set_attr "length" "*,*,*,*,*,4,4,4,4,4,4,4,8,8,*,*,*,*,*,*,*,*,4,*,4,*,*,*,*,*,4,8")
++   (set_attr "predicable" "yes,no,yes,no,no,yes,no,no,no,no,no,yes,no,no,yes,yes,yes,no,no,no,no,no,no,no,no,no,no,no,no,no,no,no")
++   (set_attr "cpu_facility" "av1,av1,av1,av2,av2,*,*,*,*,*,*,*,*,*,*,*,*,*,*,*,*,*,*,av2,av2,*,*,av2,*,*,av2,*")])
+ 
+ ;; Sometimes generated by the epilogue code.  We don't want to
+ ;; recognize these addresses in general, because the limm is costly,
+@@ -1755,10 +1768,10 @@
+ ; We avoid letting this pattern use LP_COUNT as a register by specifying
+ ;  register class 'W' instead of 'w'.
+ (define_insn_and_split "*addsi3_mixed"
+-  ;;                                                      0       1   2   3   4   5   6    7     8    9     a   b c   d    e   f  10
+-  [(set (match_operand:SI 0 "dest_reg_operand"          "=Rcq#q,Rcq,Rcw,Rcw,Rcq,Rcb,Rcq, Rcw, Rcqq,Rcqq,    W,  W,W,  W,Rcqq,Rcw,  W")
+-	(plus:SI (match_operand:SI 1 "register_operand" "%0,      c,  0,  c,  0,  0,Rcb,   0, Rcqq,   0,    c,  c,0,  0,   0,  0,  c")
+-		 (match_operand:SI 2 "nonmemory_operand" "cL,     0, cL,  0,CL2,Csp,CM4,cCca,RcqqK,  cO,cLCmL,Cca,I,C2a, Cal,Cal,Cal")))]
++  ;;                                                      0       1    2    3   4   5   6     7    8   9   a    b     c   d e   f  10  11  12
++  [(set (match_operand:SI 0 "dest_reg_operand"          "=Rcq#q,Rcq,   h,!*Rsd,Rcq,Rcb,Rcq, Rcqq,Rcqq,Rcw,Rcw, Rcw,    W,  W,W,  W,Rcqq,Rcw,  W")
++	(plus:SI (match_operand:SI 1 "register_operand" "%0,      c,   0, Rcqq,  0,  0,Rcb, Rcqq,   0,  0,  c,   0,    c,  c,0,  0,   0,  0,  c")
++		 (match_operand:SI 2 "nonmemory_operand" "cL,     0, Cm1,    L,CL2,Csp,CM4,RcqqK,  cO, cL,  0,cCca,cLCmL,Cca,I,C2a, Cal,Cal,Cal")))]
+   ""
+ {
+   arc_output_addsi (operands, arc_ccfsm_cond_exec_p (), true);
+@@ -1769,16 +1782,16 @@
+    && GET_CODE (PATTERN (insn)) != COND_EXEC"
+   [(set (match_dup 0) (match_dup 3)) (set (match_dup 0) (match_dup 4))]
+   "split_addsi (operands);"
+-  [(set_attr "type" "*,*,*,*,two_cycle_core,two_cycle_core,*,two_cycle_core,*,*,*,two_cycle_core,*,two_cycle_core,*,*,*")
++  [(set_attr "type" "*,*,*,*,two_cycle_core,two_cycle_core,*,*,*,*,*,two_cycle_core,*,two_cycle_core,*,two_cycle_core,*,*,*")
+    (set (attr "iscompact")
+ 	(cond [(match_test "~arc_output_addsi (operands, false, false) & 2")
+ 	       (const_string "false")
+ 	       (match_operand 2 "long_immediate_operand" "")
+ 	       (const_string "maybe_limm")]
+ 	      (const_string "maybe")))
+-   (set_attr "length" "*,*,4,4,*,*,*,4,*,*,4,4,4,4,*,8,8")
+-   (set_attr "predicable" "no,no,yes,yes,no,no,no,yes,no,no,no,no,no,no,no,yes,no")
+-   (set_attr "cond" "canuse,canuse,canuse,canuse,canuse,canuse,nocond,canuse,nocond,nocond,nocond,nocond,canuse_limm,canuse_limm,canuse,canuse,nocond")
++   (set_attr "length"     "*,*,*,*,*,*,*,*,*,4,4,4,4,4,4,4,*,8,8")
++   (set_attr "predicable" "no,no,no,no,no,no,no,no,no,yes,yes,yes,no,no,no,no,no,yes,no")
++   (set_attr "cond"       "canuse,nocond,nocond,nocond,canuse,canuse,nocond,nocond,nocond,canuse,canuse,canuse,nocond,nocond,canuse_limm,canuse_limm,canuse,canuse,nocond")
+ ])
+ 
+ ;; ARCv2 MPYW and MPYUW
+@@ -2723,13 +2736,14 @@
+ ; the casesi expander might generate a sub of zero, so we have to recognize it.
+ ; combine should make such an insn go away.
+ (define_insn_and_split "subsi3_insn"
+-  [(set (match_operand:SI 0 "dest_reg_operand"          "=Rcqq,Rcw,Rcw,w,w,w,  w,  w,  w")
+-	(minus:SI (match_operand:SI 1 "nonmemory_operand"   "0,  0, cL,c,L,I,Cal,Cal,  c")
+-		  (match_operand:SI 2 "nonmemory_operand" "Rcqq, c,  0,c,c,0,  0,  c,Cal")))]
++  [(set (match_operand:SI 0 "dest_reg_operand"           "=Rcqq,Rcqq,Rcw,Rcw,w,w,w,  w,  w,  w")
++	(minus:SI (match_operand:SI 1 "nonmemory_operand"    "0,Rcqq,  0, cL,c,L,I,Cal,Cal,  c")
++		  (match_operand:SI 2 "nonmemory_operand" "Rcqq,Rcqq,  c,  0,c,c,0,  0,  c,Cal")))]
+   "register_operand (operands[1], SImode)
+    || register_operand (operands[2], SImode)"
+   "@
+     sub%? %0,%1,%2%&
++    sub%? %0,%1,%2%&
+     sub%? %0,%1,%2
+     rsub%? %0,%2,%1
+     sub %0,%1,%2
+@@ -2743,10 +2757,12 @@
+    && GET_CODE (PATTERN (insn)) != COND_EXEC"
+   [(set (match_dup 0) (match_dup 3)) (set (match_dup 0) (match_dup 4))]
+   "split_subsi (operands);"
+-  [(set_attr "iscompact" "maybe,false,false,false,false,false,false,false, false")
+-  (set_attr "length" "*,4,4,4,4,4,8,8,8")
+-  (set_attr "predicable" "yes,yes,yes,no,no,no,yes,no,no")
+-  (set_attr "cond" "canuse,canuse,canuse,nocond,nocond,canuse_limm,canuse,nocond,nocond")])
++  [(set_attr "iscompact" "maybe,maybe,false,false,false,false,false,false,false, false")
++  (set_attr "length" "*,*,4,4,4,4,4,8,8,8")
++  (set_attr "predicable" "yes,no,yes,yes,no,no,no,yes,no,no")
++  (set_attr "cond" "canuse,nocond,canuse,canuse,nocond,nocond,canuse_limm,canuse,nocond,nocond")
++  (set_attr "cpu_facility" "*,cd,*,*,*,*,*,*,*,*")
++  ])
+ 
+ (define_expand "subdi3"
+   [(parallel [(set (match_operand:DI 0 "dest_reg_operand" "")
+-- 
+2.7.4
+
diff --git a/toolchain/gcc/patches/6.3.0/0047-ARC-Code-size-modifications.patch b/toolchain/gcc/patches/6.3.0/0047-ARC-Code-size-modifications.patch
new file mode 100644
index 0000000..2cbdad0
--- /dev/null
+++ b/toolchain/gcc/patches/6.3.0/0047-ARC-Code-size-modifications.patch
@@ -0,0 +1,107 @@
+From 3a58d7260e0f74fa16afbca0fd18c7d57748d3de Mon Sep 17 00:00:00 2001
+From: Claudiu Zissulescu <claziss at synopsys.com>
+Date: Tue, 20 Sep 2016 13:27:56 +0200
+Subject: [PATCH 47/89] [ARC] Code size modifications.
+
+gcc/
+2016-09-20  Claudiu Zissulescu  <claziss at synopsys.com>
+
+	* config/arc/arc.c (arc_init): Use multiplier whenever we have it.
+	(arc_conditional_register_usage): Use a different allocation order
+	when optimizing for size.
+	* common/config/arc/arc-common.c (arc_option_optimization_table):
+	Section anchors default on when optimizing for size.
+---
+ gcc/common/config/arc/arc-common.c |  1 +
+ gcc/config/arc/arc.c               | 56 ++++++++++++++++++++++++++++----------
+ 2 files changed, 43 insertions(+), 14 deletions(-)
+
+diff --git a/gcc/common/config/arc/arc-common.c b/gcc/common/config/arc/arc-common.c
+index 289886006380..8a9acb6239e3 100644
+--- a/gcc/common/config/arc/arc-common.c
++++ b/gcc/common/config/arc/arc-common.c
+@@ -46,6 +46,7 @@ arc_option_init_struct (struct gcc_options *opts)
+ #define OPT_LEVELS_3_PLUS_SPEED_ONLY OPT_LEVELS_3_PLUS
+ static const struct default_options arc_option_optimization_table[] =
+   {
++    { OPT_LEVELS_SIZE, OPT_fsection_anchors, NULL, 1 },
+     { OPT_LEVELS_1_PLUS, OPT_fomit_frame_pointer, NULL, 1 },
+     { OPT_LEVELS_ALL, OPT_mRcq, NULL, 1 },
+     { OPT_LEVELS_ALL, OPT_mRcw, NULL, 1 },
+diff --git a/gcc/config/arc/arc.c b/gcc/config/arc/arc.c
+index 498bdfd422dd..379b70011f2b 100644
+--- a/gcc/config/arc/arc.c
++++ b/gcc/config/arc/arc.c
+@@ -685,6 +685,12 @@ make_pass_arc_predicate_delay_insns (gcc::context *ctxt)
+ static void
+ arc_init (void)
+ {
++  if (TARGET_V2)
++    {
++      /* I have the multiplier, then use it*/
++      if (TARGET_MPYW || TARGET_MULTI)
++	  arc_multcost = COSTS_N_INSNS (1);
++    }
+   /* Note: arc_multcost is only used in rtx_cost if speed is true.  */
+   if (arc_multcost < 0)
+     switch (arc_tune)
+@@ -1382,20 +1388,42 @@ arc_conditional_register_usage (void)
+     }
+   if (TARGET_Q_CLASS)
+     {
+-      reg_alloc_order[2] = 12;
+-      reg_alloc_order[3] = 13;
+-      reg_alloc_order[4] = 14;
+-      reg_alloc_order[5] = 15;
+-      reg_alloc_order[6] = 1;
+-      reg_alloc_order[7] = 0;
+-      reg_alloc_order[8] = 4;
+-      reg_alloc_order[9] = 5;
+-      reg_alloc_order[10] = 6;
+-      reg_alloc_order[11] = 7;
+-      reg_alloc_order[12] = 8;
+-      reg_alloc_order[13] = 9;
+-      reg_alloc_order[14] = 10;
+-      reg_alloc_order[15] = 11;
++      if (optimize_size)
++	{
++	  reg_alloc_order[0] = 0;
++	  reg_alloc_order[1] = 1;
++	  reg_alloc_order[2] = 2;
++	  reg_alloc_order[3] = 3;
++	  reg_alloc_order[4] = 12;
++	  reg_alloc_order[5] = 13;
++	  reg_alloc_order[6] = 14;
++	  reg_alloc_order[7] = 15;
++	  reg_alloc_order[8] = 4;
++	  reg_alloc_order[9] = 5;
++	  reg_alloc_order[10] = 6;
++	  reg_alloc_order[11] = 7;
++	  reg_alloc_order[12] = 8;
++	  reg_alloc_order[13] = 9;
++	  reg_alloc_order[14] = 10;
++	  reg_alloc_order[15] = 11;
++	}
++      else
++	{
++	  reg_alloc_order[2] = 12;
++	  reg_alloc_order[3] = 13;
++	  reg_alloc_order[4] = 14;
++	  reg_alloc_order[5] = 15;
++	  reg_alloc_order[6] = 1;
++	  reg_alloc_order[7] = 0;
++	  reg_alloc_order[8] = 4;
++	  reg_alloc_order[9] = 5;
++	  reg_alloc_order[10] = 6;
++	  reg_alloc_order[11] = 7;
++	  reg_alloc_order[12] = 8;
++	  reg_alloc_order[13] = 9;
++	  reg_alloc_order[14] = 10;
++	  reg_alloc_order[15] = 11;
++	}
+     }
+   if (TARGET_SIMD_SET)
+     {
+-- 
+2.7.4
+
diff --git a/toolchain/gcc/patches/6.3.0/0048-ARC-Save-restore-blink-when-in-ISR.patch b/toolchain/gcc/patches/6.3.0/0048-ARC-Save-restore-blink-when-in-ISR.patch
new file mode 100644
index 0000000..3eb5b9f
--- /dev/null
+++ b/toolchain/gcc/patches/6.3.0/0048-ARC-Save-restore-blink-when-in-ISR.patch
@@ -0,0 +1,90 @@
+From 4e94874053d1705bcafefc36d164e4e61547117d Mon Sep 17 00:00:00 2001
+From: Claudiu Zissulescu <claziss at synopsys.com>
+Date: Wed, 21 Sep 2016 13:10:29 +0200
+Subject: [PATCH 48/89] [ARC] Save/restore blink when in ISR.
+
+gcc/
+2016-09-21  Claudiu Zissulescu  <claziss at synopsys.com>
+
+	* config/arc/arc.c (arc_epilogue_uses): BLINK should be also
+	restored when in interrupt.
+	* config/arc/arc.md (simple_return): ARCv2 rtie instruction
+	doesn't have delay slot.
+	* testsuite/gcc.target/arc/interrupt-4.c: New file.
+---
+ gcc/config/arc/arc.c                       | 10 ++++++----
+ gcc/config/arc/arc.md                      |  7 ++++++-
+ gcc/testsuite/gcc.target/arc/interrupt-4.c | 15 +++++++++++++++
+ 3 files changed, 27 insertions(+), 5 deletions(-)
+ create mode 100644 gcc/testsuite/gcc.target/arc/interrupt-4.c
+
+diff --git a/gcc/config/arc/arc.c b/gcc/config/arc/arc.c
+index 379b70011f2b..d3b8a6ace4b3 100644
+--- a/gcc/config/arc/arc.c
++++ b/gcc/config/arc/arc.c
+@@ -9441,9 +9441,10 @@ arc_can_follow_jump (const rtx_insn *follower, const rtx_insn *followee)
+    Return true if REGNO should be added to the deemed uses of the epilogue.
+ 
+    We use the return address
+-   arc_return_address_regs[arc_compute_function_type (cfun)] .
+-   But also, we have to make sure all the register restore instructions
+-   are known to be live in interrupt functions.  */
++   arc_return_address_regs[arc_compute_function_type (cfun)].  But
++   also, we have to make sure all the register restore instructions
++   are known to be live in interrupt functions, plus the blink
++   register if it is clobbered by the isr.  */
+ 
+ bool
+ arc_epilogue_uses (int regno)
+@@ -9456,7 +9457,8 @@ arc_epilogue_uses (int regno)
+ 	{
+ 	  if (!fixed_regs[regno])
+ 	    return true;
+-	  return regno == arc_return_address_regs[cfun->machine->fn_type];
++	  return ((regno == arc_return_address_regs[cfun->machine->fn_type])
++		  || (regno == RETURN_ADDR_REGNUM));
+ 	}
+       else
+ 	return regno == RETURN_ADDR_REGNUM;
+diff --git a/gcc/config/arc/arc.md b/gcc/config/arc/arc.md
+index 2b239d7268f5..c8924bcaf1d6 100644
+--- a/gcc/config/arc/arc.md
++++ b/gcc/config/arc/arc.md
+@@ -4766,7 +4766,12 @@
+   output_asm_insn (\"j%!%* [%0]%&\", &reg);
+   return \"\";
+ }
+-  [(set_attr "type" "return")
++  [(set (attr "type")
++	(cond [(and (eq (symbol_ref "arc_compute_function_type (cfun)")
++			(symbol_ref "ARC_FUNCTION_ILINK1"))
++		    (match_test "TARGET_V2"))
++	       (const_string "brcc_no_delay_slot")]
++	      (const_string "return")))
+    ; predicable won't help here since the canonical rtl looks different
+    ; for branches.
+    (set (attr "cond")
+diff --git a/gcc/testsuite/gcc.target/arc/interrupt-4.c b/gcc/testsuite/gcc.target/arc/interrupt-4.c
+new file mode 100644
+index 000000000000..ea6596eb1283
+--- /dev/null
++++ b/gcc/testsuite/gcc.target/arc/interrupt-4.c
+@@ -0,0 +1,15 @@
++#if defined (__ARCHS__) || defined (__ARCEM__)
++#define RILINK "ilink"
++#else
++#define RILINK "ilink1"
++#endif
++
++extern int gpio_int;
++extern int read_reg (int);
++
++void __attribute__ ((interrupt(RILINK)))
++isr_handler (void)
++{
++  gpio_int = read_reg (1);
++}
++/* { dg-final { scan-assembler-times "blink" 2 } } */
+-- 
+2.7.4
+
diff --git a/toolchain/gcc/patches/6.3.0/0049-ARC-Fix-detection-of-long-immediate-for-load-store-o.patch b/toolchain/gcc/patches/6.3.0/0049-ARC-Fix-detection-of-long-immediate-for-load-store-o.patch
new file mode 100644
index 0000000..7d77166
--- /dev/null
+++ b/toolchain/gcc/patches/6.3.0/0049-ARC-Fix-detection-of-long-immediate-for-load-store-o.patch
@@ -0,0 +1,51 @@
+From 7bd136a42fb4ea8d3188ce80e64d348e359fea11 Mon Sep 17 00:00:00 2001
+From: Claudiu Zissulescu <claziss at synopsys.com>
+Date: Wed, 21 Sep 2016 14:59:06 +0200
+Subject: [PATCH 49/89] [ARC] Fix detection of long immediate for load/store
+ operands.
+
+ARC can use scaled offsets when loading (i.e. ld.as rA,[base,
+offset]).  Where base and offset can be a register or an immediate
+operand.  The scaling only applies on the offset part of the
+instruction.  The compiler can accept an address like this:
+
+(plus:SI (mult:SI (reg:SI 2 r2 [orig:596 _2129 ] [596])
+	          (const_int 4 [0x4]))
+	 (const_int 60 [0x3c]))
+
+Hence, to emit this instruction we place the (const_int 60) into base
+and the register into offset to take advantage of the scaled offset
+facility of the load instruction.  As a result the length of the load
+instruction is 8 bytes.  However, the long_immediate_loadstore_operand
+predicate used for calculating the length attribute doesn't recognize
+this address and returns a wrong decision leading to a wrong length
+computation for a load instruction using the above address.
+
+gcc/
+2016-09-21  Claudiu Zissulescu  <claziss at synopsys.com>
+
+	* config/arc/predicates.md (long_immediate_loadstore_operand):
+	Consider scaled addresses cases.
+---
+ gcc/config/arc/predicates.md | 5 +++++
+ 1 file changed, 5 insertions(+)
+
+diff --git a/gcc/config/arc/predicates.md b/gcc/config/arc/predicates.md
+index f85f931d4601..7824f7234d7d 100644
+--- a/gcc/config/arc/predicates.md
++++ b/gcc/config/arc/predicates.md
+@@ -148,6 +148,11 @@
+       {
+ 	rtx x = XEXP (op, 1);
+ 
++	if ((GET_CODE (XEXP (op, 0)) == MULT)
++	    && REG_P (XEXP (XEXP (op, 0), 0))
++	    && CONSTANT_P (x))
++	  return 1;
++
+ 	if (GET_CODE (x) == CONST)
+ 	  {
+ 	    x = XEXP (x, 0);
+-- 
+2.7.4
+
diff --git a/toolchain/gcc/patches/6.3.0/0050-ARC-Disable-TP-register-when-building-for-bare-metal.patch b/toolchain/gcc/patches/6.3.0/0050-ARC-Disable-TP-register-when-building-for-bare-metal.patch
new file mode 100644
index 0000000..a56804f
--- /dev/null
+++ b/toolchain/gcc/patches/6.3.0/0050-ARC-Disable-TP-register-when-building-for-bare-metal.patch
@@ -0,0 +1,58 @@
+From 502d5bb134a0a78ec5fb482910bca6b7d0d10e41 Mon Sep 17 00:00:00 2001
+From: Claudiu Zissulescu <claziss at synopsys.com>
+Date: Thu, 29 Sep 2016 12:31:05 +0200
+Subject: [PATCH 50/89] [ARC] Disable TP register when building for bare metal.
+
+gcc/
+2016-09-29  Claudiu Zissulescu  <claziss at synopsys.com>
+
+	* config/arc/elf.h (ARGET_ARC_TP_REGNO_DEFAULT): Define.
+	* config/arc/linux.h (ARGET_ARC_TP_REGNO_DEFAULT): Likewise.
+	* config/arc/arc.opt (mtp-regno): Use ARGET_ARC_TP_REGNO_DEFAULT.
+---
+ gcc/config/arc/arc.opt | 2 +-
+ gcc/config/arc/elf.h   | 5 +++++
+ gcc/config/arc/linux.h | 4 ++++
+ 3 files changed, 10 insertions(+), 1 deletion(-)
+
+diff --git a/gcc/config/arc/arc.opt b/gcc/config/arc/arc.opt
+index d8b26102d469..e96b864413f4 100644
+--- a/gcc/config/arc/arc.opt
++++ b/gcc/config/arc/arc.opt
+@@ -406,7 +406,7 @@ EnumValue
+ Enum(arc_fpu) String(fpud_all) Value(FPU_FPUD_ALL)
+ 
+ mtp-regno=
+-Target RejectNegative Joined UInteger Var(arc_tp_regno) Init(25)
++Target RejectNegative Joined UInteger Var(arc_tp_regno) Init(TARGET_ARC_TP_REGNO_DEFAULT)
+ Specify thread pointer register number.
+ 
+ mtp-regno=none
+diff --git a/gcc/config/arc/elf.h b/gcc/config/arc/elf.h
+index 96565e53115e..f4bda99030c8 100644
+--- a/gcc/config/arc/elf.h
++++ b/gcc/config/arc/elf.h
+@@ -53,3 +53,8 @@ along with GCC; see the file COPYING3.  If not see
+ #  define MULTILIB_DEFAULTS { "mcpu=" ARC_MULTILIB_CPU_DEFAULT }
+ # endif
+ #endif
++
++/* Bare-metal toolchains are not having a thread pointer register
++   set.  */
++#undef TARGET_ARC_TP_REGNO_DEFAULT
++#define TARGET_ARC_TP_REGNO_DEFAULT -1
+diff --git a/gcc/config/arc/linux.h b/gcc/config/arc/linux.h
+index e4a881fa940d..402454937d7a 100644
+--- a/gcc/config/arc/linux.h
++++ b/gcc/config/arc/linux.h
+@@ -74,3 +74,7 @@ along with GCC; see the file COPYING3.  If not see
+ /* We do not have any MULTILIB_OPTIONS specified, so there are no
+    MULTILIB_DEFAULTS.  */
+ #undef  MULTILIB_DEFAULTS
++
++/* Linux toolchains are using r25 as TLS register.  */
++#undef TARGET_ARC_TP_REGNO_DEFAULT
++#define TARGET_ARC_TP_REGNO_DEFAULT 25
+-- 
+2.7.4
+
diff --git a/toolchain/gcc/patches/6.3.0/0051-ARC-Fix-divdf3-emulation-for-arcem.patch b/toolchain/gcc/patches/6.3.0/0051-ARC-Fix-divdf3-emulation-for-arcem.patch
new file mode 100644
index 0000000..5befd2a
--- /dev/null
+++ b/toolchain/gcc/patches/6.3.0/0051-ARC-Fix-divdf3-emulation-for-arcem.patch
@@ -0,0 +1,53 @@
+From e2e4e4e5197b73743f526be8e1194e2e95ae4af0 Mon Sep 17 00:00:00 2001
+From: Claudiu Zissulescu <claziss at synopsys.com>
+Date: Thu, 29 Sep 2016 16:02:28 +0200
+Subject: [PATCH 51/89] [ARC] Fix divdf3 emulation for arcem.
+
+libgcc/
+2016-09-29  Claudiu Zissulescu  <claziss at synopsys.com>
+
+	* config/arc/ieee-754/divdf3.S (__divdf3): Use __ARCEM__.
+---
+ libgcc/config/arc/ieee-754/divdf3.S | 8 ++++----
+ 1 file changed, 4 insertions(+), 4 deletions(-)
+
+diff --git a/libgcc/config/arc/ieee-754/divdf3.S b/libgcc/config/arc/ieee-754/divdf3.S
+index 4e702dff42c5..525c2d22aa1d 100644
+--- a/libgcc/config/arc/ieee-754/divdf3.S
++++ b/libgcc/config/arc/ieee-754/divdf3.S
+@@ -189,13 +189,13 @@ __divdf3:
+ 	asl r8,DBL1H,12
+ 	lsr r12,DBL1L,20
+ 	lsr r4,r8,26
+-#ifdef __HS__
++#if defined (__ARCHS__) || defined (__ARCEM__)
+ 	add3 r10,pcl,60 ; (.Ldivtab-.) >> 3
+ #else
+ 	add3 r10,pcl,59 ; (.Ldivtab-.) >> 3
+ #endif
+ 	ld.as r4,[r10,r4]
+-#ifdef __HS__
++#if defined (__ARCHS__) || defined (__ARCEM__)
+ 	ld.as r9,[pcl,182]; [pcl,(-((.-.L7ff00000) >> 2))] ; 0x7ff00000
+ #else
+ 	ld.as r9,[pcl,180]; [pcl,(-((.-.L7ff00000) >> 2))] ; 0x7ff00000
+@@ -299,14 +299,14 @@ __divdf3:
+ 	rsub r7,r6,5
+ 	asr r10,r12,28
+ 	bmsk r4,r12,27
+-#ifdef __HS__
++#if defined (__ARCHS__) || defined (__ARCEM__)
+ 	min  r7, r7, 31
+ 	asr  DBL0L, r4, r7
+ #else
+ 	asrs DBL0L,r4,r7
+ #endif
+ 	add DBL1H,r11,r10
+-#ifdef __HS__
++#if defined (__ARCHS__) || defined (__ARCEM__)
+ 	abs.f r10, r4
+ 	sub.mi r10, r10, 1
+ #endif
+-- 
+2.7.4
+
diff --git a/toolchain/gcc/patches/6.3.0/0052-ARC-Automatic-context-save-restore-for-regular-inter.patch b/toolchain/gcc/patches/6.3.0/0052-ARC-Automatic-context-save-restore-for-regular-inter.patch
new file mode 100644
index 0000000..a8e00da
--- /dev/null
+++ b/toolchain/gcc/patches/6.3.0/0052-ARC-Automatic-context-save-restore-for-regular-inter.patch
@@ -0,0 +1,721 @@
+From 34adbf7ef266a3f94549414e050fdf48a33006b5 Mon Sep 17 00:00:00 2001
+From: Claudiu Zissulescu <claziss at synopsys.com>
+Date: Tue, 4 Oct 2016 13:00:51 +0200
+Subject: [PATCH 52/89] [ARC] Automatic context save/restore for regular
+ interrupts.
+
+The AUX_IRQ_CTRL register controls the behavior of automated register
+save and restore or prologue and epilogue sequences during a non-fast
+interrupt entry and exit, and context save and restore instructions.
+
+A user passes to the compiler the configuration of the AUX_IRQ_CTRL
+register via mirq-ctrl-saved option.  This option, specifies
+gneral-purposes registers that the processor saves/restores on
+interrupt entry and exit, and it is only valid for ARC EM and ARC HS
+cores.
+
+gcc/
+2016-10-03  Claudiu Zissulescu  <claziss at synopsys.com>
+
+	* config/arc/arc.c (irq_ctrl_saved): New variable.
+	(ARC_AUTOBLINK_IRQ_P): Define.
+	(ARC_AUTOFP_IRQ_P): Likewise.
+	(ARC_AUTO_IRQ_P): Likewise.
+	(irq_range): New function.
+	(arc_must_save_register): Likewise.
+	(arc_must_save_return_addr): Likewise.
+	(arc_dwarf_emit_irq_save_regs): Likewise.
+	(arc_override_options): Handle deferred options.
+	(MUST_SAVE_REGISTER): Deleted, replaced by arc_must_save_register.
+	(MUST_SAVE_RETURN_ADDR): Deleted, replaced by
+	arc_must_save_return_addr.
+	(arc_compute_frame_size): Handle automated save and restore of
+	registers.
+	(arc_expand_prologue): Likewise.
+	(arc_expand_epilogue): Likewise.
+	* config/arc/arc.md (stack_irq_dwarf): New unspec instruction.
+	* config/arc/arc.opt (mirq-ctrl-saved): New option.
+	* doc/invoke.texi (mirq-ctrl-saved): Document option.
+	* testsuite/gcc.target/arc/interrupt-5.c: Newfile.
+	* testsuite/gcc.target/arc/interrupt-6.c: Likewise.
+	* testsuite/gcc.target/arc/interrupt-7.c: Likewise.
+	* testsuite/gcc.target/arc/interrupt-8.c: Likewise.
+	* testsuite/gcc.target/arc/interrupt-9.c: Likewise.
+---
+ gcc/config/arc/arc.c                       | 320 ++++++++++++++++++++++++++---
+ gcc/config/arc/arc.md                      |   8 +
+ gcc/config/arc/arc.opt                     |   4 +
+ gcc/doc/invoke.texi                        |  10 +
+ gcc/testsuite/gcc.target/arc/interrupt-5.c |  19 ++
+ gcc/testsuite/gcc.target/arc/interrupt-6.c |  22 ++
+ gcc/testsuite/gcc.target/arc/interrupt-7.c |  16 ++
+ gcc/testsuite/gcc.target/arc/interrupt-8.c |  27 +++
+ gcc/testsuite/gcc.target/arc/interrupt-9.c |  17 ++
+ 9 files changed, 412 insertions(+), 31 deletions(-)
+ create mode 100644 gcc/testsuite/gcc.target/arc/interrupt-5.c
+ create mode 100644 gcc/testsuite/gcc.target/arc/interrupt-6.c
+ create mode 100644 gcc/testsuite/gcc.target/arc/interrupt-7.c
+ create mode 100644 gcc/testsuite/gcc.target/arc/interrupt-8.c
+ create mode 100644 gcc/testsuite/gcc.target/arc/interrupt-9.c
+
+diff --git a/gcc/config/arc/arc.c b/gcc/config/arc/arc.c
+index d3b8a6ace4b3..bcb3083d3ace 100644
+--- a/gcc/config/arc/arc.c
++++ b/gcc/config/arc/arc.c
+@@ -62,6 +62,7 @@ along with GCC; see the file COPYING3.  If not see
+ #include "builtins.h"
+ #include "rtl-iter.h"
+ #include "alias.h"
++#include "opts.h"
+ 
+ /* Which cpu we're compiling for (ARC600, ARC601, ARC700).  */
+ static char arc_cpu_name[10] = "";
+@@ -117,6 +118,29 @@ struct GTY (()) arc_ccfsm
+   int target_label;
+ };
+ 
++/* Status of the IRQ_CTRL_AUX register.  */
++typedef struct irq_ctrl_saved_t
++{
++  short irq_save_last_reg;      /* Last register number used by
++				   IRQ_CTRL_SAVED aux_reg.  */
++  bool  irq_save_blink;         /* True if BLINK is automatically
++				   saved.  */
++  bool  irq_save_lpcount;       /* True if LPCOUNT is automatically
++				   saved.  */
++} irq_ctrl_saved_t;
++static irq_ctrl_saved_t irq_ctrl_saved;
++
++#define ARC_AUTOBLINK_IRQ_P(FNTYPE)				\
++  (ARC_INTERRUPT_P (FNTYPE) && irq_ctrl_saved.irq_save_blink)
++
++#define ARC_AUTOFP_IRQ_P(FNTYPE)					\
++  (ARC_INTERRUPT_P (FNTYPE) && (irq_ctrl_saved.irq_save_last_reg > 26))
++
++#define ARC_AUTO_IRQ_P(FNTYPE)				\
++  (ARC_INTERRUPT_P (FNTYPE)				\
++   && (irq_ctrl_saved.irq_save_blink			\
++       || (irq_ctrl_saved.irq_save_last_reg >= 0)))
++
+ #define arc_ccfsm_current cfun->machine->ccfsm_current
+ 
+ #define ARC_CCFSM_BRANCH_DELETED_P(STATE) \
+@@ -789,11 +813,110 @@ arc_init (void)
+     }
+ }
+ 
++/* Parse -mirq-ctrl-saved= option string.  Registers may be specified
++   individually, or as ranges such as "r0-r3".  Registers accepted are
++   r0 through r31 and lp_count.  Registers and ranges must be
++   comma-separated.  */
++
++static void
++irq_range (const char *cstr)
++{
++  int i, first, last, blink, lpcount, xreg;
++  char *str, *dash, *comma;
++
++  i = strlen (cstr);
++  str = (char *) alloca (i + 1);
++  memcpy (str, cstr, i + 1);
++  blink = -1;
++  lpcount = -1;
++
++  dash = strchr (str, '-');
++  if (!dash)
++    {
++      warning (0, "value of -mirq-ctrl-saved must have form R0-REGx");
++      return;
++    }
++  *dash = '\0';
++
++  comma = strchr (dash + 1, ',');
++  if (comma)
++    *comma = '\0';
++
++  first = decode_reg_name (str);
++  if (first != 0)
++    {
++      warning (0, "first register must be R0");
++      return;
++    }
++
++  /* At this moment we do not have the register names initialized
++     accordingly.  */
++  if (!strcmp (dash + 1, "ilink"))
++    last = 29;
++  else
++    last = decode_reg_name (dash + 1);
++
++  if (last < 0)
++    {
++      warning (0, "unknown register name: %s", dash + 1);
++      return;
++    }
++
++  if (!(last & 0x01))
++    {
++      warning (0, "last register name %s must be an odd register", dash + 1);
++      return;
++    }
++
++  *dash = '-';
++
++  if (first > last)
++    {
++      warning (0, "%s-%s is an empty range", str, dash + 1);
++      return;
++    }
++
++  while (comma)
++    {
++      *comma = ',';
++      str = comma + 1;
++
++      comma = strchr (str, ',');
++      if (comma)
++	*comma = '\0';
++
++      xreg = decode_reg_name (str);
++      switch (xreg)
++	{
++	case 31:
++	  blink = 31;
++	  break;
++
++	case 60:
++	  lpcount = 60;
++	  break;
++
++	default:
++	  warning (0, "unknown register name: %s", str);
++	  return;
++	}
++    }
++
++  irq_ctrl_saved.irq_save_last_reg = last;
++  irq_ctrl_saved.irq_save_blink    = (blink == 31) || (last == 31);
++  irq_ctrl_saved.irq_save_lpcount  = (lpcount == 60);
++}
++
+ /* Check ARC options, generate derived target attributes.  */
+ 
+ static void
+ arc_override_options (void)
+ {
++  unsigned int i;
++  cl_deferred_option *opt;
++  vec<cl_deferred_option> *vopt
++    = (vec<cl_deferred_option> *) arc_deferred_options;
++
+   if (arc_cpu == PROCESSOR_NONE)
+     arc_cpu = TARGET_CPU_DEFAULT;
+ 
+@@ -827,6 +950,28 @@ arc_override_options (void)
+       gcc_unreachable ();
+     }
+ 
++  irq_ctrl_saved.irq_save_last_reg = -1;
++  irq_ctrl_saved.irq_save_blink    = false;
++  irq_ctrl_saved.irq_save_lpcount  = false;
++
++  /* Handle the deferred options.  */
++  if (vopt)
++    FOR_EACH_VEC_ELT (*vopt, i, opt)
++      {
++	switch (opt->opt_index)
++	  {
++	  case OPT_mirq_ctrl_saved_:
++	    if (TARGET_V2)
++	      irq_range (opt->arg);
++	    else
++	      warning (0, "option -mirq-ctrl-saved valid only for ARC v2 processors");
++	    break;
++
++	  default:
++	    gcc_unreachable();
++	  }
++      }
++
+   /* Set cpu flags accordingly to architecture/selected cpu.  The cpu
+      specific flags are set in arc-common.c.  The architecture forces
+      the default hardware configurations in, regardless what command
+@@ -2219,15 +2364,43 @@ arc_compute_function_type (struct function *fun)
+    code like this.  The number of frames that use __builtin_eh_return
+    is pretty low, so optimising them is not critical right now.  */
+ 
+-#define MUST_SAVE_REGISTER(regno, interrupt_p)				\
+-  (((regno) != RETURN_ADDR_REGNUM && (regno) != FRAME_POINTER_REGNUM	\
+-    && (df_regs_ever_live_p (regno)					\
+-	&& (!call_used_regs[regno] || interrupt_p)))			\
+-   || (flag_pic && crtl->uses_pic_offset_table				\
+-       && regno == PIC_OFFSET_TABLE_REGNUM)				\
+-   || (crtl->calls_eh_return && (regno > 2 && regno < 27)))
++static bool
++arc_must_save_register (int regno, struct function *func)
++{
++  enum arc_function_type fn_type = arc_compute_function_type (func);
++  bool irq_auto_save_p = ((irq_ctrl_saved.irq_save_last_reg >= regno)
++			  && ARC_INTERRUPT_P (fn_type));
++
++  if ((regno) != RETURN_ADDR_REGNUM
++      && (regno) != FRAME_POINTER_REGNUM
++      && df_regs_ever_live_p (regno)
++      && (!call_used_regs[regno]
++	  || ARC_INTERRUPT_P (fn_type))
++      /* Do not emit code for auto saved regs.  */
++      && !irq_auto_save_p)
++    return true;
++
++  if (flag_pic && crtl->uses_pic_offset_table
++      && regno == PIC_OFFSET_TABLE_REGNUM)
++    return true;
++
++  if (crtl->calls_eh_return && (regno > 2 && regno < 27))
++    return true;
++
++  return false;
++}
++
++/* Return true if the return address must be saved in the current function,
++   otherwise return false.  */
++
++static bool
++arc_must_save_return_addr (struct function *func)
++{
++  if (func->machine->frame_info.save_return_addr)
++    return true;
+ 
+-#define MUST_SAVE_RETURN_ADDR	(cfun->machine->frame_info.save_return_addr)
++  return false;
++}
+ 
+ /* Helper function to wrap FRAME_POINTER_NEEDED.  We do this as
+    FRAME_POINTER_NEEDED will not be true until the IRA (Integrated
+@@ -2245,9 +2418,9 @@ arc_compute_function_type (struct function *fun)
+ 
+    As the frame pointer is handled as a special case in our prologue
+    and epilogue code it must not be saved and restored using the
+-   MUST_SAVE_REGISTER mechanism otherwise we run into issues where GCC
+-   believes that the function is not using a frame pointer and that
+-   the value in the fp register is the frame pointer, while the
++   arc_must_save_register mechanism otherwise we run into issues where
++   GCC believes that the function is not using a frame pointer and
++   that the value in the fp register is the frame pointer, while the
+    prologue and epilogue are busy saving and restoring the fp
+    register.  This issue is fixed in this commit too.
+ 
+@@ -2317,8 +2490,6 @@ arc_compute_frame_size (void)
+   unsigned int total_size, var_size, args_size, pretend_size, extra_size;
+   unsigned int reg_size, reg_offset;
+   unsigned int gmask;
+-  enum arc_function_type fn_type;
+-  int interrupt_p;
+   struct arc_frame_info *frame_info;
+   int size;
+ 
+@@ -2343,15 +2514,13 @@ arc_compute_frame_size (void)
+ 
+   reg_size = 0;
+   gmask = 0;
+-  fn_type = arc_compute_function_type (cfun);
+-  interrupt_p = ARC_INTERRUPT_P (fn_type);
+ 
+   for (regno = 0; regno <= 31; regno++)
+     {
+-      if (MUST_SAVE_REGISTER (regno, interrupt_p))
++      if (arc_must_save_register (regno, cfun))
+ 	{
+ 	  reg_size += UNITS_PER_WORD;
+-	  gmask |= 1 << regno;
++	  gmask |= 1L << regno;
+ 	}
+     }
+ 
+@@ -2384,7 +2553,7 @@ arc_compute_frame_size (void)
+     }
+ 
+   extra_size = 0;
+-  if (MUST_SAVE_RETURN_ADDR)
++  if (arc_must_save_return_addr (cfun))
+     extra_size = 4;
+   if (arc_frame_pointer_needed ())
+     extra_size += 4;
+@@ -2606,6 +2775,77 @@ arc_save_restore (rtx base_reg,
+ int arc_return_address_regs[4]
+   = {0, RETURN_ADDR_REGNUM, ILINK1_REGNUM, ILINK2_REGNUM};
+ 
++
++/* Build dwarf information when the context is saved via AUX_IRQ_CTRL
++   mechanism.  */
++
++static void
++arc_dwarf_emit_irq_save_regs (void)
++{
++  rtx tmp, par, insn, reg;
++  int i, offset, j;
++
++  par = gen_rtx_SEQUENCE (VOIDmode,
++			  rtvec_alloc (irq_ctrl_saved.irq_save_last_reg + 1
++				       + irq_ctrl_saved.irq_save_blink
++				       + irq_ctrl_saved.irq_save_lpcount
++				       + 1));
++
++  /* Build the stack adjustment note for unwind info.  */
++  j = 0;
++  offset = UNITS_PER_WORD * (irq_ctrl_saved.irq_save_last_reg + 1
++			     + irq_ctrl_saved.irq_save_blink
++			     + irq_ctrl_saved.irq_save_lpcount);
++  tmp = plus_constant (Pmode, stack_pointer_rtx, -1 * offset);
++  tmp = gen_rtx_SET (stack_pointer_rtx, tmp);
++  RTX_FRAME_RELATED_P (tmp) = 1;
++  XVECEXP (par, 0, j++) = tmp;
++
++  offset -= UNITS_PER_WORD;
++
++  /* 1st goes LP_COUNT.  */
++  if (irq_ctrl_saved.irq_save_lpcount)
++    {
++      reg = gen_rtx_REG (SImode, 60);
++      tmp = plus_constant (Pmode, stack_pointer_rtx, offset);
++      tmp = gen_frame_mem (SImode, tmp);
++      tmp = gen_rtx_SET (tmp, reg);
++      RTX_FRAME_RELATED_P (tmp) = 1;
++      XVECEXP (par, 0, j++) = tmp;
++      offset -= UNITS_PER_WORD;
++    }
++
++  /* 2nd goes BLINK.  */
++  if (irq_ctrl_saved.irq_save_blink)
++    {
++      reg = gen_rtx_REG (SImode, 31);
++      tmp = plus_constant (Pmode, stack_pointer_rtx, offset);
++      tmp = gen_frame_mem (SImode, tmp);
++      tmp = gen_rtx_SET (tmp, reg);
++      RTX_FRAME_RELATED_P (tmp) = 1;
++      XVECEXP (par, 0, j++) = tmp;
++      offset -= UNITS_PER_WORD;
++    }
++
++  /* Build the parallel of the remaining registers recorded as saved
++     for unwind.  */
++  for (i = irq_ctrl_saved.irq_save_last_reg; i >= 0; i--)
++    {
++      reg = gen_rtx_REG (SImode, i);
++      tmp = plus_constant (Pmode, stack_pointer_rtx, offset);
++      tmp = gen_frame_mem (SImode, tmp);
++      tmp = gen_rtx_SET (tmp, reg);
++      RTX_FRAME_RELATED_P (tmp) = 1;
++      XVECEXP (par, 0, j++) = tmp;
++      offset -= UNITS_PER_WORD;
++    }
++
++  /* Dummy insn used to anchor the dwarf info.  */
++  insn = emit_insn (gen_stack_irq_dwarf());
++  add_reg_note (insn, REG_FRAME_RELATED_EXPR, par);
++  RTX_FRAME_RELATED_P (insn) = 1;
++}
++
+ /* Set up the stack and frame pointer (if desired) for the function.  */
+ 
+ void
+@@ -2619,6 +2859,7 @@ arc_expand_prologue (void)
+      Change the stack layout so that we rather store a high register with the
+      PRE_MODIFY, thus enabling more short insn generation.)  */
+   int first_offset = 0;
++  enum arc_function_type fn_type = arc_compute_function_type (cfun);
+ 
+   /* Compute total frame size.  */
+   size = arc_compute_frame_size ();
+@@ -2642,30 +2883,41 @@ arc_expand_prologue (void)
+       frame_size_to_allocate -= cfun->machine->frame_info.pretend_size;
+     }
+ 
++  /* IRQ using automatic save mechanism will save the register before
++     anything we do.  */
++  if (ARC_AUTO_IRQ_P (fn_type))
++    {
++      arc_dwarf_emit_irq_save_regs ();
++    }
++
+   /* The home-grown ABI says link register is saved first.  */
+-  if (MUST_SAVE_RETURN_ADDR)
++  if (arc_must_save_return_addr (cfun)
++      && !ARC_AUTOBLINK_IRQ_P (fn_type))
+     {
+       rtx ra = gen_rtx_REG (SImode, RETURN_ADDR_REGNUM);
+-      rtx mem = gen_frame_mem (Pmode, gen_rtx_PRE_DEC (Pmode, stack_pointer_rtx));
++      rtx mem = gen_frame_mem (Pmode,
++			       gen_rtx_PRE_DEC (Pmode,
++						stack_pointer_rtx));
+ 
+       frame_move_inc (mem, ra, stack_pointer_rtx, 0);
+       frame_size_to_allocate -= UNITS_PER_WORD;
+-
+-    } /* MUST_SAVE_RETURN_ADDR */
++    }
+ 
+   /* Save any needed call-saved regs (and call-used if this is an
+      interrupt handler) for ARCompact ISA.  */
+   if (cfun->machine->frame_info.reg_size)
+     {
+       first_offset = -cfun->machine->frame_info.reg_size;
++
+       /* N.B. FRAME_POINTER_MASK and RETURN_ADDR_MASK are cleared in gmask.  */
+       arc_save_restore (stack_pointer_rtx, gmask, 0, &first_offset);
+       frame_size_to_allocate -= cfun->machine->frame_info.reg_size;
+     }
+ 
+-
+-  /* Save frame pointer if needed.  */
+-  if (arc_frame_pointer_needed ())
++  /* Save frame pointer if needed.  First save the FP on stack, if not
++     autosaved.  */
++  if (arc_frame_pointer_needed ()
++      && !ARC_AUTOFP_IRQ_P (fn_type))
+     {
+       rtx addr = gen_rtx_PLUS (Pmode, stack_pointer_rtx,
+ 			       GEN_INT (-UNITS_PER_WORD + first_offset));
+@@ -2675,6 +2927,11 @@ arc_expand_prologue (void)
+       frame_move_inc (mem, frame_pointer_rtx, stack_pointer_rtx, 0);
+       frame_size_to_allocate -= UNITS_PER_WORD;
+       first_offset = 0;
++    }
++
++  /* Emit mov fp,sp.  */
++  if (arc_frame_pointer_needed ())
++    {
+       frame_move (frame_pointer_rtx, stack_pointer_rtx);
+     }
+ 
+@@ -2743,7 +3000,8 @@ arc_expand_epilogue (int sibcall_p)
+ 
+ 
+   /* Restore any saved registers.  */
+-  if (arc_frame_pointer_needed ())
++  if (arc_frame_pointer_needed ()
++      && !ARC_AUTOFP_IRQ_P (fn_type))
+     {
+       rtx addr = gen_rtx_POST_INC (Pmode, stack_pointer_rtx);
+ 
+@@ -2781,14 +3039,15 @@ arc_expand_epilogue (int sibcall_p)
+ 	    : satisfies_constraint_C2a (GEN_INT (first_offset))))
+        /* Also do this if we have both gprs and return
+ 	  address to restore, and they both would need a LIMM.  */
+-       || (MUST_SAVE_RETURN_ADDR
+-	   && !SMALL_INT ((cfun->machine->frame_info.reg_size + first_offset) >> 2)
+-	   && cfun->machine->frame_info.gmask))
++      || (arc_must_save_return_addr (cfun)
++	  && !SMALL_INT ((cfun->machine->frame_info.reg_size + first_offset) >> 2)
++	  && cfun->machine->frame_info.gmask))
+     {
+       frame_stack_add (first_offset);
+       first_offset = 0;
+     }
+-  if (MUST_SAVE_RETURN_ADDR)
++  if (arc_must_save_return_addr (cfun)
++      && !ARC_AUTOBLINK_IRQ_P (fn_type))
+     {
+       rtx ra = gen_rtx_REG (Pmode, RETURN_ADDR_REGNUM);
+       int ra_offs = cfun->machine->frame_info.reg_size + first_offset;
+@@ -2853,7 +3112,6 @@ arc_expand_epilogue (int sibcall_p)
+ 			   & ~(FRAME_POINTER_MASK | RETURN_ADDR_MASK), 1, &first_offset);
+     }
+ 
+-
+   /* The rest of this function does the following:
+      ARCompact    : handle epilogue_delay, restore sp (phase-2), return
+   */
+diff --git a/gcc/config/arc/arc.md b/gcc/config/arc/arc.md
+index c8924bcaf1d6..30cc237ec84f 100644
+--- a/gcc/config/arc/arc.md
++++ b/gcc/config/arc/arc.md
+@@ -6194,6 +6194,14 @@
+    (set_attr "iscompact" "maybe,false")
+    (set_attr "predicable" "no,no")])
+ 
++;; Dummy pattern used as a place holder for automatically saved
++;; registers.
++(define_insn "stack_irq_dwarf"
++  [(unspec_volatile [(const_int 1)] VUNSPEC_ARC_STACK_IRQ)]
++  ""
++  ""
++  [(set_attr "length" "0")])
++
+ ;; include the arc-FPX instructions
+ (include "fpx.md")
+ 
+diff --git a/gcc/config/arc/arc.opt b/gcc/config/arc/arc.opt
+index e96b864413f4..dde2d49cce0b 100644
+--- a/gcc/config/arc/arc.opt
++++ b/gcc/config/arc/arc.opt
+@@ -426,3 +426,7 @@ Enable unaligned word and halfword accesses to packed data.
+ 
+ TargetVariable
+ unsigned int arc_seen_options = 0
++
++mirq-ctrl-saved=
++Target RejectNegative Joined Var(arc_deferred_options) Defer
++Specifies the registers that the processor saves on an interrupt entry and exit.
+diff --git a/gcc/doc/invoke.texi b/gcc/doc/invoke.texi
+index c4d574660c1a..f3436e006511 100644
+--- a/gcc/doc/invoke.texi
++++ b/gcc/doc/invoke.texi
+@@ -591,6 +591,7 @@ Objective-C and Objective-C++ Dialects}.
+ -mnorm -mspfp -mspfp-compact -mspfp-fast -msimd -msoft-float -mswap @gol
+ -mcrc -mdsp-packa -mdvbf -mlock -mmac-d16 -mmac-24 -mrtsc -mswape @gol
+ -mtelephony -mxy -misize -mannotate-align -marclinux -marclinux_prof @gol
++-mirq-ctrl-saved @gol
+ -mlong-calls -mmedium-calls -msdata @gol
+ -mvolatile-cache -mtp-regno=@var{regno} @gol
+ -malign-call -mauto-modify-reg -mbbit-peephole -mno-brcc @gol
+@@ -13535,6 +13536,15 @@ hardware extensions.  Not available for ARC EM at .
+ 
+ @end table
+ 
++ at item -mirq-ctrl-saved="REGS"
++ at opindex mirq-ctrl-saved
++Specifies gneral-purposes registers that the processor saves/restores
++on interrupt entry and exit.  Permited values: r0-r29, fp, blink, and
++lp_count.  Registers needs to be specified as ranges such as "r0-r3".
++A register range always starts with r0.  Registers blink and lp_count
++can be specified individually.  Only valid for ARC EM and ARC HS
++cores.
++
+ @end table
+ 
+ The following options are passed through to the assembler, and also
+diff --git a/gcc/testsuite/gcc.target/arc/interrupt-5.c b/gcc/testsuite/gcc.target/arc/interrupt-5.c
+new file mode 100644
+index 000000000000..ee01d760d90b
+--- /dev/null
++++ b/gcc/testsuite/gcc.target/arc/interrupt-5.c
+@@ -0,0 +1,19 @@
++/* { dg-do compile } */
++/* { dg-skip-if "Not available for ARCv1" { arc700 ||  arc6xx } } */
++/* { dg-options "-O2 -mirq-ctrl-saved=r0-r3,blink" } */
++
++/* Check if the registers R0-R3,blink are automatically saved. */
++
++extern int bar (void *);
++
++void  __attribute__ ((interrupt("ilink")))
++foo(void)
++{
++  bar (0);
++  __asm__ volatile ( "" : : : "r0","r1","r2","r3");
++}
++/* { dg-final { scan-assembler-not "st.*r0,\\\[sp" } } */
++/* { dg-final { scan-assembler-not "st.*r1,\\\[sp" } } */
++/* { dg-final { scan-assembler-not "st.*r2,\\\[sp" } } */
++/* { dg-final { scan-assembler-not "st.*r3,\\\[sp" } } */
++/* { dg-final { scan-assembler-not "push_s blink" } } */
+diff --git a/gcc/testsuite/gcc.target/arc/interrupt-6.c b/gcc/testsuite/gcc.target/arc/interrupt-6.c
+new file mode 100644
+index 000000000000..509ff3021248
+--- /dev/null
++++ b/gcc/testsuite/gcc.target/arc/interrupt-6.c
+@@ -0,0 +1,22 @@
++/* { dg-do compile } */
++/* { dg-skip-if "Not available for ARCv1" { arc700 || arc6xx } } */
++/* { dg-options "-O2 -mirq-ctrl-saved=r0-ilink" } */
++
++#include <alloca.h>
++
++/* Check if ilink is recognized. Check how FP and BLINK are saved.
++   BLINK is saved last on the stack because the IRQ autosave will do
++   first r0-ilink.  To avoid this ABI exception, one needs to autosave
++   always blink when using the IRQ autosave feature.  */
++
++extern int bar (void *);
++
++void  __attribute__ ((interrupt("ilink")))
++foo(void)
++{
++  int *p = alloca (10);
++  bar (p);
++}
++/* { dg-final { scan-assembler-not ".*fp,\\\[sp" } } */
++/* { dg-final { scan-assembler "ld.*blink,\\\[sp\\\]" } } */
++/* { dg-final { scan-assembler "push_s.*blink" } } */
+diff --git a/gcc/testsuite/gcc.target/arc/interrupt-7.c b/gcc/testsuite/gcc.target/arc/interrupt-7.c
+new file mode 100644
+index 000000000000..547dfd380bb8
+--- /dev/null
++++ b/gcc/testsuite/gcc.target/arc/interrupt-7.c
+@@ -0,0 +1,16 @@
++/* { dg-do compile } */
++/* { dg-skip-if "Not available for ARCv1" { arc700 ||  arc6xx } } */
++/* { dg-options "-O2 -mirq-ctrl-saved=r0-r17,blink" } */
++
++/* Check if the registers R0-R17,blink are automatically saved. */
++
++void  __attribute__ ((interrupt("ilink")))
++foo(void)
++{
++  __asm__ volatile ( "" : : : "r13","r14","r15","r16");
++}
++/* { dg-final { scan-assembler-not "st.*r13,\\\[sp" } } */
++/* { dg-final { scan-assembler-not "st.*r14,\\\[sp" } } */
++/* { dg-final { scan-assembler-not "st.*r15,\\\[sp" } } */
++/* { dg-final { scan-assembler-not "st.*r16,\\\[sp" } } */
++/* { dg-final { scan-assembler-not "push_s blink" } } */
+diff --git a/gcc/testsuite/gcc.target/arc/interrupt-8.c b/gcc/testsuite/gcc.target/arc/interrupt-8.c
+new file mode 100644
+index 000000000000..60fd87b43951
+--- /dev/null
++++ b/gcc/testsuite/gcc.target/arc/interrupt-8.c
+@@ -0,0 +1,27 @@
++/* { dg-do compile } */
++/* { dg-skip-if "Not available for ARCv1" { arc700 || arc6xx } } */
++/* { dg-options "-O2 -mirq-ctrl-saved=r0-r17" } */
++
++/* Check if the registers R0-R17 are automatically saved.  GP is saved
++   by the compiler.  */
++
++int a;
++
++void  __attribute__ ((interrupt("ilink")))
++foo(void)
++{
++  __asm__ volatile ( "" : : : "r0","r1","r2","r3");
++  __asm__ volatile ( "" : : : "r13","r14","r15","r16");
++  a++;
++}
++/* { dg-final { scan-assembler-not "st.*r13,\\\[sp" } } */
++/* { dg-final { scan-assembler-not "st.*r14,\\\[sp" } } */
++/* { dg-final { scan-assembler-not "st.*r15,\\\[sp" } } */
++/* { dg-final { scan-assembler-not "st.*r16,\\\[sp" } } */
++/* { dg-final { scan-assembler "st.*gp,\\\[sp,-4\\\]" } } */
++/* { dg-final { scan-assembler "ld.*gp,\\\[sp\\\]" } } */
++/* { dg-final { scan-assembler-not "st.*r0,\\\[sp" } } */
++/* { dg-final { scan-assembler-not "st.*r1,\\\[sp" } } */
++/* { dg-final { scan-assembler-not "st.*r2,\\\[sp" } } */
++/* { dg-final { scan-assembler-not "st.*r3,\\\[sp" } } */
++/* { dg-final { scan-assembler "rtie" } } */
+diff --git a/gcc/testsuite/gcc.target/arc/interrupt-9.c b/gcc/testsuite/gcc.target/arc/interrupt-9.c
+new file mode 100644
+index 000000000000..4547fef8410f
+--- /dev/null
++++ b/gcc/testsuite/gcc.target/arc/interrupt-9.c
+@@ -0,0 +1,17 @@
++/* { dg-do compile } */
++/* { dg-require-effective-target archs }*/
++/* { dg-options "-O0 -mirq-ctrl-saved=r0-fp" } */
++
++/* Check if we get the move operation between fp and sp.  */
++
++void __attribute__ ((interrupt("ilink")))
++handler1 (void)
++{
++  asm (""
++       :
++       :
++       : "r0", "r1", "r2", "r3", "r4",
++         "r5", "r6", "r7", "r8", "r9");
++}
++/* { dg-final { scan-assembler "mov.*fp,sp" } } */
++/* { dg-final { scan-assembler-not ".*fp,\\\[sp" } } */
+-- 
+2.7.4
+
diff --git a/toolchain/gcc/patches/6.3.0/0053-ARC-Fast-interrupts-support.patch b/toolchain/gcc/patches/6.3.0/0053-ARC-Fast-interrupts-support.patch
new file mode 100644
index 0000000..df53ef5
--- /dev/null
+++ b/toolchain/gcc/patches/6.3.0/0053-ARC-Fast-interrupts-support.patch
@@ -0,0 +1,575 @@
+From d44aad6d17172957f9dd8dd63bca85a96f873765 Mon Sep 17 00:00:00 2001
+From: Claudiu Zissulescu <claziss at synopsys.com>
+Date: Tue, 4 Oct 2016 17:34:51 +0200
+Subject: [PATCH 53/89] [ARC] Fast interrupts support.
+
+When a processor enters a fast interrupts handler, and duplicate
+register banks are configured, the processor saves the user context by
+saving the registers in the main register bank to these additional
+registers in the duplicate register bank.  In this fast interrupt
+context, when you specify the rgf_banked_regs option,the compiler does
+not save the registers duplicated in the additional register bank are
+not saved.
+
+gcc/
+2016-10-04  Claudiu Zissulescu  <claziss at synopsys.com>
+	    Andrew Burgess  <andrew.burgess at embecosm.com>
+
+	* config/arc/arc.c (ARC_AUTOBLINK_IRQ_P): Consider fast interrupts
+	case also.
+	(ARC_AUTOFP_IRQ_P): Likewise.
+	(ARC_AUTO_IRQ_P): Likewise.
+	(rgf_banked_register_count): New variable.
+	(parse_mrgf_banked_regs_option): New function.
+	(arc_override_options): Handle rgf_banked_regs option.
+	(arc_handle_interrupt_attribute): Add firq option.
+	(arc_compute_function_type): Return fast irq type when required.
+	(arc_must_save_register): Handle fast interrupts.
+	(arc_expand_prologue): Do not emit dwarf info for fast interrupts.
+	(arc_return_address_regs): Update.
+	* config/arc/arc.h (arc_return_address_regs): Update.
+	(arc_function_type): Add fast interrupt type.
+	(ARC_INTERRUPT_P): Update.
+	(RC_FAST_INTERRUPT_P): Define.
+	* config/arc/arc.md (simple_return): Update for fast interrupts.
+	(p_return_i): Likewise.
+	* config/arc/arc.opt (mrgf-banked-regs): New option.
+	* doc/invoke.texi (mrgf-banked-regs): Document.
+	* testsuite/gcc.target/arc/firq-1.c: New file.
+	* testsuite/gcc.target/arc/firq-2.c: Likewise.
+	* testsuite/gcc.target/arc/firq-3.c: Likewise.
+	* testsuite/gcc.target/arc/firq-4.c: Likewise.
+	* testsuite/gcc.target/arc/firq-5.c: Likewise.
+	* testsuite/gcc.target/arc/firq-6.c: Likewise.
+---
+ gcc/config/arc/arc.c                  | 106 +++++++++++++++++++++++++++-------
+ gcc/config/arc/arc.h                  |  13 +++--
+ gcc/config/arc/arc.md                 |   9 ++-
+ gcc/config/arc/arc.opt                |   4 ++
+ gcc/doc/invoke.texi                   |  14 ++++-
+ gcc/testsuite/gcc.target/arc/firq-1.c |  27 +++++++++
+ gcc/testsuite/gcc.target/arc/firq-2.c |  31 ++++++++++
+ gcc/testsuite/gcc.target/arc/firq-3.c |  40 +++++++++++++
+ gcc/testsuite/gcc.target/arc/firq-4.c |  31 ++++++++++
+ gcc/testsuite/gcc.target/arc/firq-5.c |  15 +++++
+ gcc/testsuite/gcc.target/arc/firq-6.c |  21 +++++++
+ 11 files changed, 280 insertions(+), 31 deletions(-)
+ create mode 100644 gcc/testsuite/gcc.target/arc/firq-1.c
+ create mode 100644 gcc/testsuite/gcc.target/arc/firq-2.c
+ create mode 100644 gcc/testsuite/gcc.target/arc/firq-3.c
+ create mode 100644 gcc/testsuite/gcc.target/arc/firq-4.c
+ create mode 100644 gcc/testsuite/gcc.target/arc/firq-5.c
+ create mode 100644 gcc/testsuite/gcc.target/arc/firq-6.c
+
+diff --git a/gcc/config/arc/arc.c b/gcc/config/arc/arc.c
+index bcb3083d3ace..282e7d45aa4b 100644
+--- a/gcc/config/arc/arc.c
++++ b/gcc/config/arc/arc.c
+@@ -131,16 +131,25 @@ typedef struct irq_ctrl_saved_t
+ static irq_ctrl_saved_t irq_ctrl_saved;
+ 
+ #define ARC_AUTOBLINK_IRQ_P(FNTYPE)				\
+-  (ARC_INTERRUPT_P (FNTYPE) && irq_ctrl_saved.irq_save_blink)
+-
+-#define ARC_AUTOFP_IRQ_P(FNTYPE)					\
+-  (ARC_INTERRUPT_P (FNTYPE) && (irq_ctrl_saved.irq_save_last_reg > 26))
+-
+-#define ARC_AUTO_IRQ_P(FNTYPE)				\
+-  (ARC_INTERRUPT_P (FNTYPE)				\
+-   && (irq_ctrl_saved.irq_save_blink			\
++  ((ARC_INTERRUPT_P (FNTYPE)					\
++    && irq_ctrl_saved.irq_save_blink)				\
++   || (ARC_FAST_INTERRUPT_P (FNTYPE)				\
++       && rgf_banked_register_count > 8))
++
++#define ARC_AUTOFP_IRQ_P(FNTYPE)				\
++  ((ARC_INTERRUPT_P (FNTYPE)					\
++    && (irq_ctrl_saved.irq_save_last_reg > 26))			\
++  || (ARC_FAST_INTERRUPT_P (FNTYPE)				\
++      && rgf_banked_register_count > 8))
++
++#define ARC_AUTO_IRQ_P(FNTYPE)					\
++  (ARC_INTERRUPT_P (FNTYPE) && !ARC_FAST_INTERRUPT_P (FNTYPE)	\
++   && (irq_ctrl_saved.irq_save_blink				\
+        || (irq_ctrl_saved.irq_save_last_reg >= 0)))
+ 
++/* Number of registers in second bank for FIRQ support.  */
++static int rgf_banked_register_count;
++
+ #define arc_ccfsm_current cfun->machine->ccfsm_current
+ 
+ #define ARC_CCFSM_BRANCH_DELETED_P(STATE) \
+@@ -907,6 +916,27 @@ irq_range (const char *cstr)
+   irq_ctrl_saved.irq_save_lpcount  = (lpcount == 60);
+ }
+ 
++/* Parse -mrgf-banked-regs=NUM option string.  Valid values for NUM are 4,
++   8, 16, or 32.  */
++
++static void
++parse_mrgf_banked_regs_option (const char *arg)
++{
++  long int val;
++  char *end_ptr;
++
++  errno = 0;
++  val = strtol (arg, &end_ptr, 10);
++  if (errno != 0 || *arg == '\0' || *end_ptr != '\0'
++      || (val != 0 && val != 4 && val != 8 && val != 16 && val != 32))
++    {
++      error ("invalid number in -mrgf-banked-regs=%s "
++	     "valid values are 0, 4, 8, 16, or 32", arg);
++      return;
++    }
++  rgf_banked_register_count = (int) val;
++}
++
+ /* Check ARC options, generate derived target attributes.  */
+ 
+ static void
+@@ -954,6 +984,8 @@ arc_override_options (void)
+   irq_ctrl_saved.irq_save_blink    = false;
+   irq_ctrl_saved.irq_save_lpcount  = false;
+ 
++  rgf_banked_register_count = 0;
++
+   /* Handle the deferred options.  */
+   if (vopt)
+     FOR_EACH_VEC_ELT (*vopt, i, opt)
+@@ -967,6 +999,13 @@ arc_override_options (void)
+ 	      warning (0, "option -mirq-ctrl-saved valid only for ARC v2 processors");
+ 	    break;
+ 
++	  case OPT_mrgf_banked_regs_:
++	    if (TARGET_V2)
++	      parse_mrgf_banked_regs_option (opt->arg);
++	    else
++	      warning (0, "option -mrgf-banked-regs valid only for ARC v2 processors");
++	    break;
++
+ 	  default:
+ 	    gcc_unreachable();
+ 	  }
+@@ -1755,9 +1794,9 @@ arc_handle_interrupt_attribute (tree *, tree name, tree args, int,
+ 	       name);
+       *no_add_attrs = true;
+     }
+-  else if (strcmp (TREE_STRING_POINTER (value), "ilink1")
+-	   && strcmp (TREE_STRING_POINTER (value), "ilink2")
+-	   && !TARGET_V2)
++  else if (!TARGET_V2
++	   && strcmp (TREE_STRING_POINTER (value), "ilink1")
++	   && strcmp (TREE_STRING_POINTER (value), "ilink2"))
+     {
+       warning (OPT_Wattributes,
+ 	       "argument of %qE attribute is not \"ilink1\" or \"ilink2\"",
+@@ -1765,10 +1804,11 @@ arc_handle_interrupt_attribute (tree *, tree name, tree args, int,
+       *no_add_attrs = true;
+     }
+   else if (TARGET_V2
+-	   && strcmp (TREE_STRING_POINTER (value), "ilink"))
++	   && strcmp (TREE_STRING_POINTER (value), "ilink")
++	   && strcmp (TREE_STRING_POINTER (value), "firq"))
+     {
+       warning (OPT_Wattributes,
+-	       "argument of %qE attribute is not \"ilink\"",
++	       "argument of %qE attribute is not \"ilink\" or \"firq\"",
+ 	       name);
+       *no_add_attrs = true;
+     }
+@@ -2328,6 +2368,8 @@ arc_compute_function_type (struct function *fun)
+ 	    fn_type = ARC_FUNCTION_ILINK1;
+ 	  else if (!strcmp (TREE_STRING_POINTER (value), "ilink2"))
+ 	    fn_type = ARC_FUNCTION_ILINK2;
++	  else if (!strcmp (TREE_STRING_POINTER (value), "firq"))
++	    fn_type = ARC_FUNCTION_FIRQ;
+ 	  else
+ 	    gcc_unreachable ();
+ 	  break;
+@@ -2369,7 +2411,29 @@ arc_must_save_register (int regno, struct function *func)
+ {
+   enum arc_function_type fn_type = arc_compute_function_type (func);
+   bool irq_auto_save_p = ((irq_ctrl_saved.irq_save_last_reg >= regno)
+-			  && ARC_INTERRUPT_P (fn_type));
++			  && ARC_AUTO_IRQ_P (fn_type));
++  bool firq_auto_save_p = ARC_FAST_INTERRUPT_P (fn_type);
++
++  switch (rgf_banked_register_count)
++    {
++    case 4:
++      firq_auto_save_p &= (regno < 4);
++      break;
++    case 8:
++      firq_auto_save_p &= ((regno < 4) || ((regno > 11) && (regno < 16)));
++      break;
++    case 16:
++      firq_auto_save_p &= ((regno < 4) || ((regno > 9) && (regno < 16))
++			   || ((regno > 25) && (regno < 29))
++			   || ((regno > 29) && (regno < 32)));
++      break;
++    case 32:
++      firq_auto_save_p &= (regno != 29) && (regno < 32);
++      break;
++    default:
++      firq_auto_save_p = false;
++      break;
++    }
+ 
+   if ((regno) != RETURN_ADDR_REGNUM
+       && (regno) != FRAME_POINTER_REGNUM
+@@ -2377,7 +2441,8 @@ arc_must_save_register (int regno, struct function *func)
+       && (!call_used_regs[regno]
+ 	  || ARC_INTERRUPT_P (fn_type))
+       /* Do not emit code for auto saved regs.  */
+-      && !irq_auto_save_p)
++      && !irq_auto_save_p
++      && !firq_auto_save_p)
+     return true;
+ 
+   if (flag_pic && crtl->uses_pic_offset_table
+@@ -2771,11 +2836,6 @@ arc_save_restore (rtx base_reg,
+     }
+ } /* arc_save_restore */
+ 
+-
+-int arc_return_address_regs[4]
+-  = {0, RETURN_ADDR_REGNUM, ILINK1_REGNUM, ILINK2_REGNUM};
+-
+-
+ /* Build dwarf information when the context is saved via AUX_IRQ_CTRL
+    mechanism.  */
+ 
+@@ -2885,7 +2945,8 @@ arc_expand_prologue (void)
+ 
+   /* IRQ using automatic save mechanism will save the register before
+      anything we do.  */
+-  if (ARC_AUTO_IRQ_P (fn_type))
++  if (ARC_AUTO_IRQ_P (fn_type)
++      && !ARC_FAST_INTERRUPT_P (fn_type))
+     {
+       arc_dwarf_emit_irq_save_regs ();
+     }
+@@ -9695,6 +9756,9 @@ arc_can_follow_jump (const rtx_insn *follower, const rtx_insn *followee)
+   return true;
+ }
+ 
++int arc_return_address_regs[5] =
++  {0, RETURN_ADDR_REGNUM, ILINK1_REGNUM, ILINK2_REGNUM, ILINK1_REGNUM};
++
+ /* Implement EPILOGUE__USES.
+    Return true if REGNO should be added to the deemed uses of the epilogue.
+ 
+diff --git a/gcc/config/arc/arc.h b/gcc/config/arc/arc.h
+index 5ca2bb5ffcd0..86bc6088fbcd 100644
+--- a/gcc/config/arc/arc.h
++++ b/gcc/config/arc/arc.h
+@@ -1337,7 +1337,7 @@ do { \
+ 
+ /* To translate the return value of arc_function_type into a register number
+    to jump through for function return.  */
+-extern int arc_return_address_regs[4];
++extern int arc_return_address_regs[5];
+ 
+ /* Debugging information.  */
+ 
+@@ -1477,10 +1477,15 @@ enum arc_function_type {
+   ARC_FUNCTION_UNKNOWN, ARC_FUNCTION_NORMAL,
+   /* These are interrupt handlers.  The name corresponds to the register
+      name that contains the return address.  */
+-  ARC_FUNCTION_ILINK1, ARC_FUNCTION_ILINK2
++  ARC_FUNCTION_ILINK1, ARC_FUNCTION_ILINK2,
++  /* Fast interrupt is only available on ARCv2 processors.  */
++  ARC_FUNCTION_FIRQ
+ };
+-#define ARC_INTERRUPT_P(TYPE) \
+-((TYPE) == ARC_FUNCTION_ILINK1 || (TYPE) == ARC_FUNCTION_ILINK2)
++#define ARC_INTERRUPT_P(TYPE)						\
++  (((TYPE) == ARC_FUNCTION_ILINK1) || ((TYPE) == ARC_FUNCTION_ILINK2)	\
++   || ((TYPE) == ARC_FUNCTION_FIRQ))
++
++#define ARC_FAST_INTERRUPT_P(TYPE) ((TYPE) == ARC_FUNCTION_FIRQ)
+ 
+ /* Compute the type of a function from its DECL.  Needed for EPILOGUE_USES.  */
+ struct function;
+diff --git a/gcc/config/arc/arc.md b/gcc/config/arc/arc.md
+index 30cc237ec84f..4306d7229437 100644
+--- a/gcc/config/arc/arc.md
++++ b/gcc/config/arc/arc.md
+@@ -4756,8 +4756,8 @@
+     = gen_rtx_REG (Pmode,
+ 		   arc_return_address_regs[arc_compute_function_type (cfun)]);
+ 
+-  if (arc_compute_function_type (cfun) == ARC_FUNCTION_ILINK1
+-      && TARGET_V2)
++  if (TARGET_V2
++      && ARC_INTERRUPT_P (arc_compute_function_type (cfun)))
+   {
+     return \"rtie\";
+   }
+@@ -4767,8 +4767,7 @@
+   return \"\";
+ }
+   [(set (attr "type")
+-	(cond [(and (eq (symbol_ref "arc_compute_function_type (cfun)")
+-			(symbol_ref "ARC_FUNCTION_ILINK1"))
++	(cond [(and (match_test "ARC_INTERRUPT_P (arc_compute_function_type (cfun))")
+ 		    (match_test "TARGET_V2"))
+ 	       (const_string "brcc_no_delay_slot")]
+ 	      (const_string "return")))
+@@ -4798,7 +4797,7 @@
+ 		      (simple_return) (pc)))]
+   "reload_completed
+    && !(TARGET_V2
+-     && arc_compute_function_type (cfun) == ARC_FUNCTION_ILINK1)"
++     && ARC_INTERRUPT_P (arc_compute_function_type (cfun)))"
+ {
+   rtx xop[2];
+   xop[0] = operands[0];
+diff --git a/gcc/config/arc/arc.opt b/gcc/config/arc/arc.opt
+index dde2d49cce0b..90ff4ad27f67 100644
+--- a/gcc/config/arc/arc.opt
++++ b/gcc/config/arc/arc.opt
+@@ -430,3 +430,7 @@ unsigned int arc_seen_options = 0
+ mirq-ctrl-saved=
+ Target RejectNegative Joined Var(arc_deferred_options) Defer
+ Specifies the registers that the processor saves on an interrupt entry and exit.
++
++mrgf-banked-regs=
++Target RejectNegative Joined Var(arc_deferred_options) Defer
++Specifies the number of registers replicated in second register bank on entry to fast interrupt.
+diff --git a/gcc/doc/invoke.texi b/gcc/doc/invoke.texi
+index f3436e006511..79ee47c2820f 100644
+--- a/gcc/doc/invoke.texi
++++ b/gcc/doc/invoke.texi
+@@ -591,7 +591,7 @@ Objective-C and Objective-C++ Dialects}.
+ -mnorm -mspfp -mspfp-compact -mspfp-fast -msimd -msoft-float -mswap @gol
+ -mcrc -mdsp-packa -mdvbf -mlock -mmac-d16 -mmac-24 -mrtsc -mswape @gol
+ -mtelephony -mxy -misize -mannotate-align -marclinux -marclinux_prof @gol
+--mirq-ctrl-saved @gol
++-mirq-ctrl-saved -mrgf-banked-regs @gol
+ -mlong-calls -mmedium-calls -msdata @gol
+ -mvolatile-cache -mtp-regno=@var{regno} @gol
+ -malign-call -mauto-modify-reg -mbbit-peephole -mno-brcc @gol
+@@ -13545,6 +13545,18 @@ A register range always starts with r0.  Registers blink and lp_count
+ can be specified individually.  Only valid for ARC EM and ARC HS
+ cores.
+ 
++ at item -mrgf-banked-regs="NUMBER"
++ at opindex mrgf-banked-regs
++Specifies the number of registers replicated in second register bank
++on entry to fast interrupt.  Fast interrupts are interrupts with the
++highest priority level P0.  These interrupts save only PC and STATUS32
++registers to avoid memory transactions during interrupt entry and exit
++sequences.  Use this option when you are using fast interrupts in an
++ARC V2 family processor.
++
++Permitted values are 4, 8, 16, 32 and specify the number of registers
++that are covered by the second register bank.
++
+ @end table
+ 
+ The following options are passed through to the assembler, and also
+diff --git a/gcc/testsuite/gcc.target/arc/firq-1.c b/gcc/testsuite/gcc.target/arc/firq-1.c
+new file mode 100644
+index 000000000000..87f408793dc9
+--- /dev/null
++++ b/gcc/testsuite/gcc.target/arc/firq-1.c
+@@ -0,0 +1,27 @@
++/* { dg-do compile } */
++/* { dg-require-effective-target archs }*/
++/* { dg-options "-O0 -mll64 -mirq-ctrl-saved=r0-r9" } */
++
++/* Check that on archs the 'firq' interrupt function type is
++   available, these are the fast interrupts.  For fast interrupts,
++   despite the use of 'irq-ctrl-saved', no registers are automatically
++   saved on entry to the function, and so, in the following register
++   r0 to r9 should all be saved to the stack.
++
++   We also take the opportunity to check the use of the 'rtie'
++   instruction at the end of the interrupt function.  */
++
++void __attribute__ ((interrupt("firq")))
++handler1 (void)
++{
++  asm (""
++       :
++       :
++       : "r0", "r1", "r2", "r3", "r4",
++	 "r5", "r6", "r7", "r8", "r9");
++}
++/* { dg-final { scan-assembler-times "r2,\\\[sp,\[0-9\]+\\\]" 2 } } */
++/* { dg-final { scan-assembler-times "r4,\\\[sp,\[0-9\]+\\\]" 2 } } */
++/* { dg-final { scan-assembler-times "r6,\\\[sp,\[0-9\]+\\\]" 2 } } */
++/* { dg-final { scan-assembler-times "r8,\\\[sp,\[0-9\]+\\\]" 2 } } */
++/* { dg-final { scan-assembler "rtie" } } */
+diff --git a/gcc/testsuite/gcc.target/arc/firq-2.c b/gcc/testsuite/gcc.target/arc/firq-2.c
+new file mode 100644
+index 000000000000..dc7dafca11a3
+--- /dev/null
++++ b/gcc/testsuite/gcc.target/arc/firq-2.c
+@@ -0,0 +1,31 @@
++/* { dg-do compile } */
++/* { dg-require-effective-target archs }*/
++/* { dg-options "-O0 -mll64 -mirq-ctrl-saved=r0-r9 -mrgf-banked-regs=4" } */
++
++/* Check that on archs the 'firq' interrupt function type is
++   available, these are the fast interrupts.  For fast interrupts,
++   despite the use of 'irq-ctrl-saved', no registers are automatically
++   saved on stack on entry to the function.  However, the cpu save via
++   bank switch R0-R3.
++
++   We also take the opportunity to check the use of the 'rtie' instruction
++   at the end of the interrupt function.  */
++
++void __attribute__ ((interrupt("firq")))
++handler1 (void)
++{
++  asm (""
++       :
++       :
++       : "r0", "r1", "r2", "r3", "r4",
++         "r5", "r6", "r7", "r8", "r9");
++}
++/* { dg-final { scan-assembler-not "r0,\\\[sp" } } */
++/* { dg-final { scan-assembler-not "push.*r0" } } */
++/* { dg-final { scan-assembler-not "r1,\\\[sp" } } */
++/* { dg-final { scan-assembler-not "r2,\\\[sp" } } */
++/* { dg-final { scan-assembler-not "r3,\\\[sp" } } */
++/* { dg-final { scan-assembler "st.*r4,\\\[sp" } } */
++/* { dg-final { scan-assembler "st.*r6,\\\[sp,\[0-9\]+\\\]" } } */
++/* { dg-final { scan-assembler "st.*r8,\\\[sp,\[0-9\]+\\\]" } } */
++/* { dg-final { scan-assembler "rtie" } } */
+diff --git a/gcc/testsuite/gcc.target/arc/firq-3.c b/gcc/testsuite/gcc.target/arc/firq-3.c
+new file mode 100644
+index 000000000000..a1d604d8ef75
+--- /dev/null
++++ b/gcc/testsuite/gcc.target/arc/firq-3.c
+@@ -0,0 +1,40 @@
++/* { dg-do compile } */
++/* { dg-require-effective-target archs }*/
++/* { dg-options "-O2 -mll64 -mrgf-banked-regs=8" } */
++
++/* Check if R4 to R11 and R16-R27 are correctly saved on stack.  */
++
++void __attribute__ ((interrupt("firq")))
++handler1 (void)
++{
++  asm volatile (""
++		:
++		:
++		: "r0", "r1", "r2", "r3", "r4",
++		  "r5", "r6", "r7", "r8", "r9",
++		  "r10", "r11", "r12", "r13", "r14",
++		  "r15", "r16", "r17", "r18", "r19",
++		  "r20", "r21", "r22", "r23", "r24",
++		  "r25", "fp");
++}
++/* { dg-final { scan-assembler-not "r0,\\\[sp" } } */
++/* { dg-final { scan-assembler-not "push.*r0" } } */
++/* { dg-final { scan-assembler-not "r1,\\\[sp" } } */
++/* { dg-final { scan-assembler-not "r2,\\\[sp" } } */
++/* { dg-final { scan-assembler-not "r3,\\\[sp" } } */
++/* { dg-final { scan-assembler-not "r12,\\\[sp" } } */
++/* { dg-final { scan-assembler-not "r13,\\\[sp" } } */
++/* { dg-final { scan-assembler-not "r14,\\\[sp" } } */
++/* { dg-final { scan-assembler-not "r15,\\\[sp" } } */
++
++/* { dg-final { scan-assembler-times "r4,\\\[sp" 2 } } */
++/* { dg-final { scan-assembler-times "r6,\\\[sp,\[0-9\]+\\\]" 2 } } */
++/* { dg-final { scan-assembler-times "r8,\\\[sp,\[0-9\]+\\\]" 2 } } */
++/* { dg-final { scan-assembler-times "r10,\\\[sp,\[0-9\]+\\\]" 2 } } */
++/* { dg-final { scan-assembler-times "r16,\\\[sp,\[0-9\]+\\\]" 2 } } */
++/* { dg-final { scan-assembler-times "r18,\\\[sp,\[0-9\]+\\\]" 2 } } */
++/* { dg-final { scan-assembler-times "r20,\\\[sp,\[0-9\]+\\\]" 2 } } */
++/* { dg-final { scan-assembler-times "r24,\\\[sp,\[0-9\]+\\\]" 2 } } */
++/* { dg-final { scan-assembler-times "fp,\\\[sp," 2 } } */
++
++/* { dg-final { scan-assembler "rtie" } } */
+diff --git a/gcc/testsuite/gcc.target/arc/firq-4.c b/gcc/testsuite/gcc.target/arc/firq-4.c
+new file mode 100644
+index 000000000000..03d3746a500d
+--- /dev/null
++++ b/gcc/testsuite/gcc.target/arc/firq-4.c
+@@ -0,0 +1,31 @@
++/* { dg-do compile } */
++/* { dg-require-effective-target archs }*/
++/* { dg-options "-O2 -mll64 -mrgf-banked-regs=16" } */
++
++/* Check if R4-R9 and R16-R25 are correctly saved on stack.  */
++
++void __attribute__ ((interrupt("firq")))
++handler1 (void)
++{
++  asm volatile (""
++		:
++		:
++		: "r0", "r1", "r2", "r3", "r4",
++		  "r5", "r6", "r7", "r8", "r9",
++		  "r10", "r11", "r12", "r13", "r14",
++		  "r15", "r16", "r17", "r18", "r19",
++		  "r20", "r21", "r22", "r23", "r24",
++		  "r25", "fp");
++}
++/* { dg-final { scan-assembler-times "r4,\\\[sp" 2 } } */
++/* { dg-final { scan-assembler-times "r6,\\\[sp,\[0-9\]+\\\]" 2 } } */
++/* { dg-final { scan-assembler-times "r8,\\\[sp,\[0-9\]+\\\]" 2 } } */
++
++/* { dg-final { scan-assembler-times "r16,\\\[sp,\[0-9\]+\\\]" 2 } } */
++/* { dg-final { scan-assembler-times "r18,\\\[sp,\[0-9\]+\\\]" 2 } } */
++/* { dg-final { scan-assembler-times "r20,\\\[sp,\[0-9\]+\\\]" 2 } } */
++/* { dg-final { scan-assembler-times "r24,\\\[sp,\[0-9\]+\\\]" 2 } } */
++
++/* { dg-final { scan-assembler-not "fp,\\\[sp" } } */
++/* { dg-final { scan-assembler-not "push.*fp" } } */
++/* { dg-final { scan-assembler "mov_s.*fp,sp" } } */
+diff --git a/gcc/testsuite/gcc.target/arc/firq-5.c b/gcc/testsuite/gcc.target/arc/firq-5.c
+new file mode 100644
+index 000000000000..29f17a3f0ccc
+--- /dev/null
++++ b/gcc/testsuite/gcc.target/arc/firq-5.c
+@@ -0,0 +1,15 @@
++/* { dg-do compile } */
++/* { dg-require-effective-target archs }*/
++/* { dg-options "-O2 -mrgf-banked-regs=16" } */
++
++/* Check if blink is pushed on the stack or not.   */
++
++extern void bar (void);
++
++void __attribute__ ((interrupt("firq")))
++handler1 (void)
++{
++  bar ();
++}
++/* { dg-final { scan-assembler-not "push.*blink" } } */
++/* { dg-final { scan-assembler-not "pop.*blink" } } */
+diff --git a/gcc/testsuite/gcc.target/arc/firq-6.c b/gcc/testsuite/gcc.target/arc/firq-6.c
+new file mode 100644
+index 000000000000..9421200d6304
+--- /dev/null
++++ b/gcc/testsuite/gcc.target/arc/firq-6.c
+@@ -0,0 +1,21 @@
++/* { dg-do compile } */
++/* { dg-require-effective-target archs }*/
++/* { dg-options "-O2 -mll64 -mrgf-banked-regs=32" } */
++
++/* Check if we have any register saved on stack.  */
++
++void __attribute__ ((interrupt("firq")))
++handler1 (void)
++{
++  asm volatile (""
++		:
++		:
++		: "r0", "r1", "r2", "r3", "r4",
++		  "r5", "r6", "r7", "r8", "r9",
++		  "r10", "r11", "r12", "r13", "r14",
++		  "r15", "r16", "r17", "r18", "r19",
++		  "r20", "r21", "r22", "r23", "r24",
++		  "r25", "fp");
++}
++/* { dg-final { scan-assembler-not "(s|l)(t|d)d.*r\[0-9\]+,\\\[sp,\[0-9\]+\\\]" } } */
++/* { dg-final { scan-assembler "mov_s.*fp,sp" } } */
+-- 
+2.7.4
+
diff --git a/toolchain/gcc/patches/6.3.0/0054-ARC-Add-support-for-QuarkSE2-EM-cpu.patch b/toolchain/gcc/patches/6.3.0/0054-ARC-Add-support-for-QuarkSE2-EM-cpu.patch
new file mode 100644
index 0000000..fed1163
--- /dev/null
+++ b/toolchain/gcc/patches/6.3.0/0054-ARC-Add-support-for-QuarkSE2-EM-cpu.patch
@@ -0,0 +1,269 @@
+From 05584c58a95a9d16a5a92aaab0bd9bbbee36b5c9 Mon Sep 17 00:00:00 2001
+From: Claudiu Zissulescu <claziss at synopsys.com>
+Date: Wed, 5 Oct 2016 15:02:32 +0200
+Subject: [PATCH 54/89] [ARC] Add support for QuarkSE2 EM cpu.
+
+gcc/
+2016-10-05  Claudiu Zissulescu  <claziss at synopsys.com>
+
+	* config/arc/arc-arches.def: Recognize Quarkse2 options as valid
+	ones for ARC EM architecture.
+	* config/arc/arc-cpus.def (quarkse2_em): New cpu definition.
+	* config/arc/arc-options.def (FL_FPX_QUARK2): Define.
+	(FL_QUARK2): Define.
+	* config/arc/arc-opts.h (FPX_QK2): Define.
+	(FPU_FPUDA_QK2): Likewise.
+	* config/arc/arc-tables.opt: Regenerate.
+	* config/arc/arc.h (TARGET_FPU_QUARK2): Define.
+	* config/arc/arc.md (divsf3): Allow it for QuarkSE2 cpus as well.
+	(sqrtsf2): Likewise.
+	* config/arc/fpx.md (divsf3_quark): Allow it for QuarkSE2 cpus as
+	well.
+	(sqrtsf2_quark): Likewise.
+	* config/arc/genmultilib.awk (ARC_CPU): Create quark2 multilib
+	option.
+	* config/arc/t-multilib: Regenerate.
+	* config/arc/arc-c.def (__ARC_FPU_QUARK2__): Define.
+	* config/arc/driver-arc.c (arc_cpu_to_as): Consider fpuda for
+	QuarkSE2 when assembling.
+	* Doc/invoke.texi (ARC options): Document quarkse2_em mcpu option.
+---
+ gcc/config/arc/arc-arches.def  | 2 +-
+ gcc/config/arc/arc-c.def       | 1 +
+ gcc/config/arc/arc-cpus.def    | 1 +
+ gcc/config/arc/arc-options.def | 2 ++
+ gcc/config/arc/arc-opts.h      | 4 ++++
+ gcc/config/arc/arc-tables.opt  | 3 +++
+ gcc/config/arc/arc.h           | 5 ++++-
+ gcc/config/arc/arc.md          | 8 ++++----
+ gcc/config/arc/driver-arc.c    | 2 +-
+ gcc/config/arc/fpx.md          | 4 ++--
+ gcc/config/arc/genmultilib.awk | 2 ++
+ gcc/config/arc/t-multilib      | 5 +++--
+ gcc/doc/invoke.texi            | 5 +++++
+ 13 files changed, 33 insertions(+), 11 deletions(-)
+
+diff --git a/gcc/config/arc/arc-arches.def b/gcc/config/arc/arc-arches.def
+index db96ce1241cb..846cb85f91e9 100644
+--- a/gcc/config/arc/arc-arches.def
++++ b/gcc/config/arc/arc-arches.def
+@@ -19,7 +19,7 @@
+ 
+ ARC_ARCH("arcem", em, FL_MPYOPT_1_6 | FL_DIVREM | FL_CD | FL_NORM	\
+ 	 | FL_BS | FL_SWAP | FL_FPUS | FL_SPFP | FL_DPFP		\
+-	 | FL_SIMD | FL_FPUDA | FL_QUARK, 0)
++	 | FL_SIMD | FL_FPUDA | FL_QUARK | FL_QUARK2, 0)
+ ARC_ARCH("archs", hs, FL_MPYOPT_7_9 | FL_DIVREM | FL_NORM | FL_CD	\
+ 	 | FL_ATOMIC | FL_LL64 | FL_BS | FL_SWAP			\
+ 	 | FL_FPUS | FL_FPUD,						\
+diff --git a/gcc/config/arc/arc-c.def b/gcc/config/arc/arc-c.def
+index fd643760d88e..6f5da99033f2 100644
+--- a/gcc/config/arc/arc-c.def
++++ b/gcc/config/arc/arc-c.def
+@@ -59,6 +59,7 @@ ARC_C_DEF ("__ARC_FPU_SP_FMA__", TARGET_FP_SP_FUSED)
+ ARC_C_DEF ("__ARC_FPU_DP_FMA__", TARGET_FP_DP_FUSED)
+ ARC_C_DEF ("__ARC_FPU_ASSIST__", TARGET_FP_DP_AX)
+ ARC_C_DEF ("__ARC_FPX_QUARK__",  TARGET_FPX_QUARK)
++ARC_C_DEF ("__ARC_FPU_QUARK2__", TARGET_FPU_QUARK2)
+ 
+ /* To be deprecated.  */
+ ARC_C_DEF ("__A6__",     TARGET_ARC600)
+diff --git a/gcc/config/arc/arc-cpus.def b/gcc/config/arc/arc-cpus.def
+index 8782bd5e9263..fe1390360f24 100644
+--- a/gcc/config/arc/arc-cpus.def
++++ b/gcc/config/arc/arc-cpus.def
+@@ -24,6 +24,7 @@ ARC_CPU (em4_dmips, em, FL_MPYOPT_2|FL_CD|FL_DIVREM|FL_NORM|FL_SWAP|FL_BS, NONE)
+ ARC_CPU (em4_fpus,  em, FL_MPYOPT_2|FL_CD|FL_DIVREM|FL_NORM|FL_SWAP|FL_BS|FL_FPU_FPUS, NONE)
+ ARC_CPU (em4_fpuda, em, FL_MPYOPT_2|FL_CD|FL_DIVREM|FL_NORM|FL_SWAP|FL_BS|FL_FPU_FPUDA, NONE)
+ ARC_CPU (quarkse_em, em, FL_MPYOPT_3|FL_CD|FL_DIVREM|FL_NORM|FL_SWAP|FL_BS|FL_FPX_QUARK|FL_SPFP|FL_DPFP, NONE)
++ARC_CPU (quarkse2_em, em, FL_MPYOPT_2|FL_CD|FL_DIVREM|FL_NORM|FL_SWAP|FL_BS|FL_FPX_QUARK2, NONE)
+ 
+ ARC_CPU (hs,         hs, 0, NONE)
+ ARC_CPU (archs,      hs, FL_MPYOPT_2|FL_DIVREM|FL_LL64, NONE)
+diff --git a/gcc/config/arc/arc-options.def b/gcc/config/arc/arc-options.def
+index 778f69d95afe..1a6a9364b0dc 100644
+--- a/gcc/config/arc/arc-options.def
++++ b/gcc/config/arc/arc-options.def
+@@ -60,11 +60,13 @@ ARC_OPTX (FL_FPU_FPUD_DIV,  (1ULL << 35), arc_fpu_build, FPU_FPUD_DIV,	"mfpu=fpu
+ ARC_OPTX (FL_FPU_FPUD_FMA,  (1ULL << 36), arc_fpu_build, FPU_FPUD_FMA,	"mfpu=fpud_fma")
+ ARC_OPTX (FL_FPU_FPUD_ALL,  (1ULL << 37), arc_fpu_build, FPU_FPUD_ALL,	"mfpu=fpud_all")
+ ARC_OPTX (FL_FPX_QUARK,	    (1ULL << 38), arc_fpu_build, FPX_QK,	"quarkse fp")
++ARC_OPTX (FL_FPX_QUARK2,    (1ULL << 39), arc_fpu_build, FPU_FPUDA_QK2,	"quarkse2 fp")
+ 
+ ARC_OPT (FL_FPUS,  (0xFULL << 26), 0, "single precission floating point")
+ ARC_OPT (FL_FPUDA, (0xFFULL << 26), 0, "double precission fp assist")
+ ARC_OPT (FL_FPUD,  (0xF0FULL << 26), 0, "double precission floating point")
+ ARC_OPT (FL_QUARK, (1ULL << 38), 0, "Quark SE fp extension")
++ARC_OPT (FL_QUARK2, (1ULL << 39), 0, "Quark SE2 fp extension")
+ 
+ /* Local Variables: */
+ /* mode: c */
+diff --git a/gcc/config/arc/arc-opts.h b/gcc/config/arc/arc-opts.h
+index 819b97c299f6..0cd2ebe8f22c 100644
+--- a/gcc/config/arc/arc-opts.h
++++ b/gcc/config/arc/arc-opts.h
+@@ -50,6 +50,8 @@ enum processor_type
+ #define FPX_DP    0x0100
+ /* Quark SE floating point instructions.  */
+ #define FPX_QK    0x0200
++/* Quark SE2 floating point instructions.  */
++#define FPX_QK2   0x0400
+ 
+ /* fpus option combi.  */
+ #define FPU_FPUS  (FPU_SP | FPU_SC)
+@@ -75,6 +77,8 @@ enum processor_type
+ #define FPU_FPUD_FMA  (FPU_FPUS_FMA | FPU_DP | FPU_DC | FPU_DF)
+ /* fpud_all option combi.  */
+ #define FPU_FPUD_ALL  (FPU_FPUS_ALL | FPU_DP | FPU_DC | FPU_DF | FPU_DD)
++/* QuarkSE2 combi.  */
++#define FPU_FPUDA_QK2 (FPU_SP | FPU_SC | FPX_DP | FPX_QK2)
+ 
+ /* Default FPU option value.  */
+ #define DEFAULT_arc_fpu_build 0x10000000
+diff --git a/gcc/config/arc/arc-tables.opt b/gcc/config/arc/arc-tables.opt
+index 41e325c91d57..20dad4a148e6 100644
+--- a/gcc/config/arc/arc-tables.opt
++++ b/gcc/config/arc/arc-tables.opt
+@@ -46,6 +46,9 @@ EnumValue
+ Enum(processor_type) String(quarkse_em) Value(PROCESSOR_quarkse_em)
+ 
+ EnumValue
++Enum(processor_type) String(quarkse2_em) Value(PROCESSOR_quarkse2_em)
++
++EnumValue
+ Enum(processor_type) String(hs) Value(PROCESSOR_hs)
+ 
+ EnumValue
+diff --git a/gcc/config/arc/arc.h b/gcc/config/arc/arc.h
+index 86bc6088fbcd..cf13a7fa9fc3 100644
+--- a/gcc/config/arc/arc.h
++++ b/gcc/config/arc/arc.h
+@@ -1631,5 +1631,8 @@ enum
+ /* Custom FP instructions used by QuarkSE EM cpu.  */
+ #define TARGET_FPX_QUARK    (TARGET_EM && TARGET_SPFP		\
+ 			     && (arc_fpu_build == FPX_QK))
+-
++/* Custom FP instructions used by QuarkSE2 EM cpu.  */
++#define TARGET_FPU_QUARK2   (TARGET_EM					\
++			     && ((arc_fpu_build				\
++				  & FPU_FPUDA_QK2) == FPU_FPUDA_QK2))
+ #endif /* GCC_ARC_H */
+diff --git a/gcc/config/arc/arc.md b/gcc/config/arc/arc.md
+index 4306d7229437..8c492750fd13 100644
+--- a/gcc/config/arc/arc.md
++++ b/gcc/config/arc/arc.md
+@@ -5922,9 +5922,9 @@
+   [(set (match_operand:SF 0 "register_operand"        "")
+ 	(div:SF (match_operand:SF 1 "nonmemory_operand" "")
+ 		(match_operand:SF 2 "nonmemory_operand" "")))]
+-  "TARGET_FPX_QUARK || TARGET_FP_SP_SQRT"
++  "TARGET_FPX_QUARK || TARGET_FP_SP_SQRT || TARGET_FPU_QUARK2"
+   "
+-  if (TARGET_FPX_QUARK)
++  if (TARGET_FPX_QUARK || TARGET_FPU_QUARK2)
+    {
+      operands[1] = force_reg (SFmode, operands[1]);
+      operands[2] = force_reg (SFmode, operands[2]);
+@@ -5941,9 +5941,9 @@
+ (define_expand "sqrtsf2"
+   [(set (match_operand:SF 0 "register_operand"           "")
+ 	(sqrt:SF (match_operand:SF 1 "nonmemory_operand" "")))]
+-  "TARGET_FPX_QUARK || TARGET_FP_SP_SQRT"
++  "TARGET_FPX_QUARK || TARGET_FP_SP_SQRT || TARGET_FPU_QUARK2"
+   "
+-  if (TARGET_FPX_QUARK)
++  if (TARGET_FPX_QUARK || TARGET_FPU_QUARK2)
+    {
+      operands[1] = force_reg (SFmode, operands[1]);
+    }
+diff --git a/gcc/config/arc/driver-arc.c b/gcc/config/arc/driver-arc.c
+index c51b70803413..7519ce50c070 100644
+--- a/gcc/config/arc/driver-arc.c
++++ b/gcc/config/arc/driver-arc.c
+@@ -56,7 +56,7 @@ arc_cpu_to_as (int argc, const char **argv)
+ 	name = "-mcode-density";
+       else
+ 	name = "";
+-      if (arc_selected_cpu->flags & FL_FPUDA)
++      if (arc_selected_cpu->flags & (FL_FPUDA | FL_QUARK2))
+ 	name = concat ("-mfpuda ", name, NULL);
+       if (arc_selected_cpu->flags & FL_SPFP)
+ 	name = concat ("-mspfp ", name, NULL);
+diff --git a/gcc/config/arc/fpx.md b/gcc/config/arc/fpx.md
+index 094319e1ce4f..a0ae3b4ed9b2 100644
+--- a/gcc/config/arc/fpx.md
++++ b/gcc/config/arc/fpx.md
+@@ -678,7 +678,7 @@
+   [(set (match_operand:SF 0 "register_operand"        "=r")
+ 	(div:SF (match_operand:SF 1 "register_operand" "r")
+ 		(match_operand:SF 2 "register_operand" "r")))]
+-  "TARGET_FPX_QUARK"
++  "TARGET_FPX_QUARK || TARGET_FPU_QUARK2"
+   "dsp_fp_div\\t%0,%1,%2"
+   [(set_attr "length" "4")
+    (set_attr "predicable" "no")
+@@ -687,7 +687,7 @@
+ (define_insn "*sqrtsf2_quark"
+   [(set (match_operand:SF 0 "register_operand"          "=r")
+ 	(sqrt:SF (match_operand:SF 1 "register_operand" "r")))]
+-  "TARGET_FPX_QUARK"
++  "TARGET_FPX_QUARK || TARGET_FPU_QUARK2"
+   "dsp_fp_sqrt\\t%0,%1"
+   [(set_attr "length" "4")
+    (set_attr "predicable" "no")
+diff --git a/gcc/config/arc/genmultilib.awk b/gcc/config/arc/genmultilib.awk
+index 61bda419c8a8..a8a50a8d17e2 100644
+--- a/gcc/config/arc/genmultilib.awk
++++ b/gcc/config/arc/genmultilib.awk
+@@ -126,6 +126,8 @@ BEGIN {
+ 	    line = line "/mmul32x16"
+ 	  else if (cpu_flg[i] == "FL_FPX_QUARK")
+ 	    line = line "/quark"
++	  else if (cpu_flg[i] == "FL_FPX_QUARK2")
++	    line = line "/quark2"
+ 	  else if (cpu_flg[i] == "FL_SPFP")
+ 	    line = line "/spfp"
+ 	  else if (cpu_flg[i] == "FL_DPFP")
+diff --git a/gcc/config/arc/t-multilib b/gcc/config/arc/t-multilib
+index 0f1c398d61f8..7e21f947621f 100644
+--- a/gcc/config/arc/t-multilib
++++ b/gcc/config/arc/t-multilib
+@@ -21,9 +21,9 @@
+ # along with GCC; see the file COPYING3.  If not see
+ # <http://www.gnu.org/licenses/>.
+ 
+-MULTILIB_OPTIONS = mcpu=em/mcpu=arcem/mcpu=em4/mcpu=em4_dmips/mcpu=em4_fpus/mcpu=em4_fpuda/mcpu=quarkse_em/mcpu=hs/mcpu=archs/mcpu=hs34/mcpu=hs38/mcpu=hs38_linux/mcpu=arc600/mcpu=arc600_norm/mcpu=arc600_mul64/mcpu=arc600_mul32x16/mcpu=arc601/mcpu=arc601_norm/mcpu=arc601_mul64/mcpu=arc601_mul32x16/mcpu=arc700/mcpu=nps400
++MULTILIB_OPTIONS = mcpu=em/mcpu=arcem/mcpu=em4/mcpu=em4_dmips/mcpu=em4_fpus/mcpu=em4_fpuda/mcpu=quarkse_em/mcpu=quarkse2_em/mcpu=hs/mcpu=archs/mcpu=hs34/mcpu=hs38/mcpu=hs38_linux/mcpu=arc600/mcpu=arc600_norm/mcpu=arc600_mul64/mcpu=arc600_mul32x16/mcpu=arc601/mcpu=arc601_norm/mcpu=arc601_mul64/mcpu=arc601_mul32x16/mcpu=arc700/mcpu=nps400
+ 
+-MULTILIB_DIRNAMES = em arcem em4 em4_dmips em4_fpus em4_fpuda quarkse_em hs archs hs34 hs38 hs38_linux arc600 arc600_norm arc600_mul64 arc600_mul32x16 arc601 arc601_norm arc601_mul64 arc601_mul32x16 arc700 nps400
++MULTILIB_DIRNAMES = em arcem em4 em4_dmips em4_fpus em4_fpuda quarkse_em quarkse2_em hs archs hs34 hs38 hs38_linux arc600 arc600_norm arc600_mul64 arc600_mul32x16 arc601 arc601_norm arc601_mul64 arc601_mul32x16 arc700 nps400
+ 
+ MULTILIB_REUSE =mcpu.arcem=mcpu.em/mmpy-option.2/mcode-density/mbarrel-shifter
+ MULTILIB_REUSE +=mcpu.em4=mcpu.em/mcode-density
+@@ -31,6 +31,7 @@ MULTILIB_REUSE +=mcpu.em4_dmips=mcpu.em/mmpy-option.2/mcode-density/mdiv-rem/mno
+ MULTILIB_REUSE +=mcpu.em4_fpus=mcpu.em/mmpy-option.2/mcode-density/mdiv-rem/mnorm/mnorm/mbarrel-shifter/mfpu.fpus
+ MULTILIB_REUSE +=mcpu.em4_fpuda=mcpu.em/mmpy-option.2/mcode-density/mdiv-rem/mnorm/mnorm/mbarrel-shifter/mfpu.fpuda
+ MULTILIB_REUSE +=mcpu.quarkse_em=mcpu.em/mmpy-option.3/mcode-density/mdiv-rem/mnorm/mnorm/mbarrel-shifter/quark/spfp/dpfp
++MULTILIB_REUSE +=mcpu.quarkse2_em=mcpu.em/mmpy-option.2/mcode-density/mdiv-rem/mnorm/mnorm/mbarrel-shifter/quark2
+ MULTILIB_REUSE +=mcpu.archs=mcpu.hs/mmpy-option.2/mdiv-rem/mll64
+ MULTILIB_REUSE +=mcpu.hs34=mcpu.hs/mmpy-option.2
+ MULTILIB_REUSE +=mcpu.hs38=mcpu.hs/mmpy-option.9/mdiv-rem/mll64
+diff --git a/gcc/doc/invoke.texi b/gcc/doc/invoke.texi
+index 79ee47c2820f..c81f1e98a809 100644
+--- a/gcc/doc/invoke.texi
++++ b/gcc/doc/invoke.texi
+@@ -13272,6 +13272,11 @@ extension.
+ Compile for ARC EM4 DMIPS cpu with single precision floating point and
+ double assists instructions.
+ 
++ at item quarkse2_em
++ at opindex quarkse2_em
++Compile for ARC EM CPU on Intel QuarkSE2 microcontroller with single
++precision floating point.
++
+ @item hs
+ @opindex hs
+ Compile for ARC HS cpu with no hardware extension, except the atomic
+-- 
+2.7.4
+
diff --git a/toolchain/gcc/patches/6.3.0/0055-ARC-Fix-move_double_src_operand-predicate.patch b/toolchain/gcc/patches/6.3.0/0055-ARC-Fix-move_double_src_operand-predicate.patch
new file mode 100644
index 0000000..9f076ac
--- /dev/null
+++ b/toolchain/gcc/patches/6.3.0/0055-ARC-Fix-move_double_src_operand-predicate.patch
@@ -0,0 +1,37 @@
+From 0a2de97b8dc588e4b43808004370e5123e5122e2 Mon Sep 17 00:00:00 2001
+From: Claudiu Zissulescu <claziss at synopsys.com>
+Date: Fri, 7 Oct 2016 16:20:16 +0200
+Subject: [PATCH 55/89] [ARC] Fix move_double_src_operand predicate.
+
+Durring compilation process, (subreg (mem ...) ...) can occur. Hence,
+we need to check if the address of mem is a valid one. This patch is
+fixing this check by directly calling the address_operand, instead of
+calling move_double_src_operand, as the latter is always checking
+against the original mode, thus, returning false when the inner and
+outer modes are different.
+
+gcc/
+2016-10-07  Claudiu Zissulescu  <claziss at synopsys.com>
+
+	* config/arc/predicates.md (move_double_src_operand): Replace the
+	call to move_double_src_operand with a call to address_operand.
+---
+ gcc/config/arc/predicates.md | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+diff --git a/gcc/config/arc/predicates.md b/gcc/config/arc/predicates.md
+index 7824f7234d7d..5c95c207758d 100644
+--- a/gcc/config/arc/predicates.md
++++ b/gcc/config/arc/predicates.md
+@@ -317,7 +317,7 @@
+       /* (subreg (mem ...) ...) can occur here if the inner part was once a
+ 	 pseudo-reg and is now a stack slot.  */
+       if (GET_CODE (SUBREG_REG (op)) == MEM)
+-	return move_double_src_operand (SUBREG_REG (op), mode);
++	return address_operand (XEXP (SUBREG_REG (op), 0), mode);
+       else
+ 	return register_operand (op, mode);
+     case MEM :
+-- 
+2.7.4
+
diff --git a/toolchain/gcc/patches/6.3.0/0056-ARC-Remove-old-prof-patterns.patch b/toolchain/gcc/patches/6.3.0/0056-ARC-Remove-old-prof-patterns.patch
new file mode 100644
index 0000000..807d93d
--- /dev/null
+++ b/toolchain/gcc/patches/6.3.0/0056-ARC-Remove-old-prof-patterns.patch
@@ -0,0 +1,107 @@
+From 853d24cf2a826ca6e1922eec3f72ee83fdc892c7 Mon Sep 17 00:00:00 2001
+From: Claudiu Zissulescu <claziss at synopsys.com>
+Date: Mon, 10 Oct 2016 13:02:28 +0200
+Subject: [PATCH 56/89] [ARC] Remove old prof patterns.
+
+gcc/
+2016-10-10  Claudiu Zissulescu  <claziss at synopsys.com>
+
+	* config/arc/arc.md (call_prof): Remove.
+	(call_value_prof): Likewise.
+	(sibcall_prof): Likewise.
+	(sibcall_value_prof): Likewise.
+---
+ gcc/config/arc/arc.md | 63 ---------------------------------------------------
+ 1 file changed, 63 deletions(-)
+
+diff --git a/gcc/config/arc/arc.md b/gcc/config/arc/arc.md
+index 8c492750fd13..a193745dc9ba 100644
+--- a/gcc/config/arc/arc.md
++++ b/gcc/config/arc/arc.md
+@@ -4111,20 +4111,6 @@
+    (set_attr "predicable" "no,no,yes,yes,no,yes,no,yes")
+    (set_attr "length" "*,*,4,4,4,4,4,8")])
+ 
+-(define_insn "call_prof"
+-  [(call (mem:SI (match_operand:SI 0 "symbolic_operand" "Cbr,Cal"))
+-	 (match_operand 1 "" ""))
+-   (clobber (reg:SI 31))
+-   (use (reg:SI 8))
+-   (use (reg:SI 9))]
+-   ""
+-  "@
+-   bl%!%* %P0;2
+-   jl%! %^%S0"
+-  [(set_attr "type" "call,call_no_delay_slot")
+-   (set_attr "predicable" "yes,yes")
+-   (set_attr "length" "4,8")])
+-
+ (define_expand "call_value"
+   ;; operand 2 is stack_size_rtx
+   ;; operand 3 is next_arg_register
+@@ -4174,22 +4160,6 @@
+ ; use it for lack of inter-procedural branch shortening.
+ ; Link-time relaxation would help...
+ 
+-
+-(define_insn "call_value_prof"
+-  [(set (match_operand 0 "dest_reg_operand" "=r,r")
+-	(call (mem:SI (match_operand:SI 1 "symbolic_operand" "Cbr,Cal"))
+-	      (match_operand 2 "" "")))
+-   (clobber (reg:SI 31))
+-   (use (reg:SI 8))
+-   (use (reg:SI 9))]
+-   ""
+-  "@
+-   bl%!%* %P1;1
+-   jl%! %^%S1"
+-  [(set_attr "type" "call,call_no_delay_slot")
+-   (set_attr "predicable" "yes,yes")
+-   (set_attr "length" "4,8")])
+-
+ (define_insn "nop"
+   [(const_int 0)]
+   ""
+@@ -4684,39 +4654,6 @@
+    (set_attr "is_SIBCALL" "yes")]
+ )
+ 
+-(define_insn "sibcall_prof"
+- [(call (mem:SI (match_operand:SI 0 "call_address_operand" "Cbr,Cal"))
+-	(match_operand 1 "" ""))
+-  (simple_return)
+-  (use (match_operand 2 "" ""))
+-  (use (reg:SI 8))
+-  (use (reg:SI 9))]
+-  ""
+-  "@
+-   b%!%* %P0;2
+-   j%! %^%S0;2"
+-  [(set_attr "type" "call,call_no_delay_slot")
+-   (set_attr "predicable" "yes")
+-   (set_attr "is_SIBCALL" "yes")]
+-)
+-
+-(define_insn "sibcall_value_prof"
+- [(set (match_operand 0 "dest_reg_operand" "")
+-       (call (mem:SI (match_operand:SI 1 "call_address_operand" "Cbr,Cal"))
+-	     (match_operand 2 "" "")))
+-  (simple_return)
+-  (use (match_operand 3 "" ""))
+-  (use (reg:SI 8))
+-  (use (reg:SI 9))]
+-  ""
+-  "@
+-   b%!%* %P1;1
+-   j%! %^%S1;1"
+-  [(set_attr "type" "call,call_no_delay_slot")
+-   (set_attr "predicable" "yes")
+-   (set_attr "is_SIBCALL" "yes")]
+-)
+-
+ (define_expand "prologue"
+   [(pc)]
+   ""
+-- 
+2.7.4
+
diff --git a/toolchain/gcc/patches/6.3.0/0057-ARC-Update-mode_dependent_address_p-hook.patch b/toolchain/gcc/patches/6.3.0/0057-ARC-Update-mode_dependent_address_p-hook.patch
new file mode 100644
index 0000000..fd62360
--- /dev/null
+++ b/toolchain/gcc/patches/6.3.0/0057-ARC-Update-mode_dependent_address_p-hook.patch
@@ -0,0 +1,40 @@
+From 0886f8cda0d8969ad02611a154f602de2f8b0fb7 Mon Sep 17 00:00:00 2001
+From: Claudiu Zissulescu <claziss at synopsys.com>
+Date: Tue, 11 Oct 2016 18:58:56 +0200
+Subject: [PATCH 57/89] [ARC] Update mode_dependent_address_p hook.
+
+Update arc_mode_dependent_address_p to avoid emitting subreg(mem (reg
+..)) when expanding by relaxing the conditions.
+
+gcc/
+2016-10-11  Claudiu Zissulescu  <claziss at synopsys.com>
+
+	* config/arc/arc.c (arc_mode_dependent_address_p): Relax
+	conditions to take advantage of various optimizations.
+---
+ gcc/config/arc/arc.c | 8 ++------
+ 1 file changed, 2 insertions(+), 6 deletions(-)
+
+diff --git a/gcc/config/arc/arc.c b/gcc/config/arc/arc.c
+index 282e7d45aa4b..7033ce960aa7 100644
+--- a/gcc/config/arc/arc.c
++++ b/gcc/config/arc/arc.c
+@@ -5964,13 +5964,9 @@ arc_mode_dependent_address_p (const_rtx addr, addr_space_t)
+ {
+   /* SYMBOL_REF is not mode dependent: it is either a small data reference,
+      which is valid for loads and stores, or a limm offset, which is valid for
+-     loads.  */
+-  /* Scaled indices are scaled by the access mode; likewise for scaled
+-     offsets, which are needed for maximum offset stores.  */
++     loads.  Scaled indices are scaled by the access mode.  */
+   if (GET_CODE (addr) == PLUS
+-      && (GET_CODE (XEXP ((addr), 0)) == MULT
+-	  || (CONST_INT_P (XEXP ((addr), 1))
+-	      && !SMALL_INT (INTVAL (XEXP ((addr), 1))))))
++      && GET_CODE (XEXP ((addr), 0)) == MULT)
+     return true;
+   return false;
+ }
+-- 
+2.7.4
+
diff --git a/toolchain/gcc/patches/6.3.0/0058-Changed-tests-to-verify-shared-option.patch b/toolchain/gcc/patches/6.3.0/0058-Changed-tests-to-verify-shared-option.patch
new file mode 100644
index 0000000..b87f0ed
--- /dev/null
+++ b/toolchain/gcc/patches/6.3.0/0058-Changed-tests-to-verify-shared-option.patch
@@ -0,0 +1,56 @@
+From c78838d08006be4fd90fe9d598f3052c27120d93 Mon Sep 17 00:00:00 2001
+From: Cupertino Miranda <cmiranda at synopsys.com>
+Date: Thu, 13 Oct 2016 16:37:18 +0200
+Subject: [PATCH 58/89] Changed tests to verify -shared option.
+
+Verify for option -shared instead of just the availability of -fpic.
+
+gcc/testsuite/
+2016-10-13  Cupertino Miranda  <cmiranda at synopsys.com>
+
+	gcc.dg/lto/pr54709_0.c: Added
+	{ dg-require-effective-target shared } to test.
+	gcc.dg/lto/pr61526_0.c: Likewise.
+	gcc.dg/lto/pr64415_0.c: Likewise.
+---
+ gcc/testsuite/gcc.dg/lto/pr54709_0.c | 1 +
+ gcc/testsuite/gcc.dg/lto/pr61526_0.c | 1 +
+ gcc/testsuite/gcc.dg/lto/pr64415_0.c | 1 +
+ 3 files changed, 3 insertions(+)
+
+diff --git a/gcc/testsuite/gcc.dg/lto/pr54709_0.c b/gcc/testsuite/gcc.dg/lto/pr54709_0.c
+index f3db5dcbbc48..69697d89158a 100644
+--- a/gcc/testsuite/gcc.dg/lto/pr54709_0.c
++++ b/gcc/testsuite/gcc.dg/lto/pr54709_0.c
+@@ -1,6 +1,7 @@
+ /* { dg-lto-do link } */
+ /* { dg-require-visibility "hidden" } */
+ /* { dg-require-effective-target fpic } */
++/* { dg-require-effective-target shared } */
+ /* { dg-extra-ld-options { -shared } } */
+ /* { dg-lto-options { { -fPIC -fvisibility=hidden -flto } } } */
+ 
+diff --git a/gcc/testsuite/gcc.dg/lto/pr61526_0.c b/gcc/testsuite/gcc.dg/lto/pr61526_0.c
+index 8a631f058ed5..d3e2c8008dbe 100644
+--- a/gcc/testsuite/gcc.dg/lto/pr61526_0.c
++++ b/gcc/testsuite/gcc.dg/lto/pr61526_0.c
+@@ -1,4 +1,5 @@
+ /* { dg-require-effective-target fpic } */
++/* { dg-require-effective-target shared } */
+ /* { dg-lto-do link } */
+ /* { dg-lto-options { { -fPIC -flto -flto-partition=1to1 } } } */
+ /* { dg-extra-ld-options { -shared } } */
+diff --git a/gcc/testsuite/gcc.dg/lto/pr64415_0.c b/gcc/testsuite/gcc.dg/lto/pr64415_0.c
+index 4faab2bac354..11218e072859 100644
+--- a/gcc/testsuite/gcc.dg/lto/pr64415_0.c
++++ b/gcc/testsuite/gcc.dg/lto/pr64415_0.c
+@@ -1,5 +1,6 @@
+ /* { dg-lto-do link } */
+ /* { dg-require-effective-target fpic } */
++/* { dg-require-effective-target shared } */
+ /* { dg-lto-options { { -O -flto -fpic } } } */
+ /* { dg-extra-ld-options { -shared } } */
+ /* { dg-extra-ld-options "-Wl,-undefined,dynamic_lookup" { target *-*-darwin* } } */
+-- 
+2.7.4
+
diff --git a/toolchain/gcc/patches/6.3.0/0059-ARC-DWARF-emitting-cleanup.patch b/toolchain/gcc/patches/6.3.0/0059-ARC-DWARF-emitting-cleanup.patch
new file mode 100644
index 0000000..597e767
--- /dev/null
+++ b/toolchain/gcc/patches/6.3.0/0059-ARC-DWARF-emitting-cleanup.patch
@@ -0,0 +1,75 @@
+From ccddb9c4a1b84975311dbec4a0354ec5f7c261cc Mon Sep 17 00:00:00 2001
+From: Claudiu Zissulescu <claziss at synopsys.com>
+Date: Mon, 17 Oct 2016 13:10:54 +0200
+Subject: [PATCH 59/89] [ARC] DWARF emitting cleanup.
+
+The use of CFA_FRAME_BASE_OFFSET and ARG_POINTER_CFA_OFFSET macros
+leads to wrong offset calculation for DW_OP_fbreg constructions.
+Remove them.
+
+gcc/
+2016-10-17  Claudiu Zissulescu  <claziss at synopsys.com>
+
+	* config/arc/arc-protos.h (arc_decl_pretend_args): Remove.
+	* config/arc/arc.c (arc_decl_pretend_args): Likewise.
+	* config/arc/arc.h (CFA_FRAME_BASE_OFFSET): Likewise.
+	(ARG_POINTER_CFA_OFFSET): Likewise.
+---
+ gcc/config/arc/arc-protos.h |  1 -
+ gcc/config/arc/arc.c        | 11 -----------
+ gcc/config/arc/arc.h        |  5 -----
+ 3 files changed, 17 deletions(-)
+
+diff --git a/gcc/config/arc/arc-protos.h b/gcc/config/arc/arc-protos.h
+index 2c11f3557bf2..7b8ceeaa13c1 100644
+--- a/gcc/config/arc/arc-protos.h
++++ b/gcc/config/arc/arc-protos.h
+@@ -109,7 +109,6 @@ extern int arc_label_align (rtx label);
+ extern bool arc_need_delay (rtx_insn *insn);
+ extern bool arc_text_label (rtx_insn *insn);
+ 
+-extern int arc_decl_pretend_args (tree decl);
+ extern bool arc_short_comparison_p (rtx, int);
+ extern bool arc_epilogue_uses (int regno);
+ extern bool arc_eh_uses (int regno);
+diff --git a/gcc/config/arc/arc.c b/gcc/config/arc/arc.c
+index 7033ce960aa7..6500e3e21f05 100644
+--- a/gcc/config/arc/arc.c
++++ b/gcc/config/arc/arc.c
+@@ -9717,17 +9717,6 @@ arc_text_label (rtx_insn *label)
+   return false;
+ }
+ 
+-/* Return the size of the pretend args for DECL.  */
+-
+-int
+-arc_decl_pretend_args (tree decl)
+-{
+-  /* struct function is in DECL_STRUCT_FUNCTION (decl), but no
+-     pretend_args there...  See PR38391.  */
+-  gcc_assert (decl == current_function_decl);
+-  return crtl->args.pretend_args_size;
+-}
+-
+ /* Without this, gcc.dg/tree-prof/bb-reorg.c fails to assemble
+   when compiling with -O2 -freorder-blocks-and-partition -fprofile-use
+   -D_PROFILE_USE; delay branch scheduling then follows a crossing jump
+diff --git a/gcc/config/arc/arc.h b/gcc/config/arc/arc.h
+index cf13a7fa9fc3..3680261e75e0 100644
+--- a/gcc/config/arc/arc.h
++++ b/gcc/config/arc/arc.h
+@@ -1560,11 +1560,6 @@ extern enum arc_function_type arc_compute_function_type (struct function *);
+ 
+ #define INIT_EXPANDERS arc_init_expanders ()
+ 
+-#define CFA_FRAME_BASE_OFFSET(FUNDECL) (-arc_decl_pretend_args ((FUNDECL)))
+-
+-#define ARG_POINTER_CFA_OFFSET(FNDECL) \
+-  (FIRST_PARM_OFFSET (FNDECL) + arc_decl_pretend_args ((FNDECL)))
+-
+ enum
+ {
+   ARC_LRA_PRIORITY_NONE, ARC_LRA_PRIORITY_NONCOMPACT, ARC_LRA_PRIORITY_COMPACT
+-- 
+2.7.4
+
diff --git a/toolchain/gcc/patches/6.3.0/0060-ARC-Use-long-jumps-for-CRT-calls.patch b/toolchain/gcc/patches/6.3.0/0060-ARC-Use-long-jumps-for-CRT-calls.patch
new file mode 100644
index 0000000..3b1e69e
--- /dev/null
+++ b/toolchain/gcc/patches/6.3.0/0060-ARC-Use-long-jumps-for-CRT-calls.patch
@@ -0,0 +1,36 @@
+From fc5f2fcf3040f940c63c4f3c6f958b1450ee0f63 Mon Sep 17 00:00:00 2001
+From: Claudiu Zissulescu <claziss at synopsys.com>
+Date: Thu, 21 Apr 2016 12:12:30 +0200
+Subject: [PATCH 60/89] [ARC] Use long jumps for CRT calls
+
+gcc/
+2016-04-21  Claudiu Zissulescu  <claziss at synopsys.com>
+
+	* config/arc/arc.h (CRT_CALL_STATIC_FUNCTION): Use long calls.
+---
+ gcc/config/arc/arc.h | 9 +++++----
+ 1 file changed, 5 insertions(+), 4 deletions(-)
+
+diff --git a/gcc/config/arc/arc.h b/gcc/config/arc/arc.h
+index 3680261e75e0..99c3e6b9b44f 100644
+--- a/gcc/config/arc/arc.h
++++ b/gcc/config/arc/arc.h
+@@ -1494,10 +1494,11 @@ extern enum arc_function_type arc_compute_function_type (struct function *);
+ /* Called by crtstuff.c to make calls to function FUNCTION that are defined in
+    SECTION_OP, and then to switch back to text section.  */
+ #undef CRT_CALL_STATIC_FUNCTION
+-#define CRT_CALL_STATIC_FUNCTION(SECTION_OP, FUNC) \
+-    asm (SECTION_OP "\n\t"				\
+-	"bl @" USER_LABEL_PREFIX #FUNC "\n"		\
+-	TEXT_SECTION_ASM_OP);
++#define CRT_CALL_STATIC_FUNCTION(SECTION_OP, FUNC)		\
++  asm (SECTION_OP "\n\t"					\
++       "add r12,pcl,@" USER_LABEL_PREFIX #FUNC "@pcl\n\t"	\
++       "jl  [r12]\n"						\
++       TEXT_SECTION_ASM_OP);
+ 
+ /* This macro expands to the name of the scratch register r12, used for
+    temporary calculations according to the ABI.  */
+-- 
+2.7.4
+
diff --git a/toolchain/gcc/patches/6.3.0/0061-ARC-Fix-typo-in-arc.opt.patch b/toolchain/gcc/patches/6.3.0/0061-ARC-Fix-typo-in-arc.opt.patch
new file mode 100644
index 0000000..7440d17
--- /dev/null
+++ b/toolchain/gcc/patches/6.3.0/0061-ARC-Fix-typo-in-arc.opt.patch
@@ -0,0 +1,35 @@
+From 38a5be64dabdf59df0c899b2224de768042a7040 Mon Sep 17 00:00:00 2001
+From: Claudiu Zissulescu <claziss at synopsys.com>
+Date: Wed, 2 Nov 2016 11:12:06 +0100
+Subject: [PATCH 61/89] [ARC] Fix typo in arc.opt
+
+gcc/
+2016-11-02  Claudiu Zissulescu  <claziss at synopsys.com>
+
+	* config/arc/arc.opt (marclinux): Fix typo.
+	(marclinux_prof): Likewise.
+---
+ gcc/config/arc/arc.opt | 4 ++--
+ 1 file changed, 2 insertions(+), 2 deletions(-)
+
+diff --git a/gcc/config/arc/arc.opt b/gcc/config/arc/arc.opt
+index 90ff4ad27f67..c8fb7892bacd 100644
+--- a/gcc/config/arc/arc.opt
++++ b/gcc/config/arc/arc.opt
+@@ -319,11 +319,11 @@ Target
+ Pass -EL option through to linker.
+ 
+ marclinux
+-target
++Target
+ Pass -marclinux option through to linker.
+ 
+ marclinux_prof
+-target
++Target
+ Pass -marclinux_prof option through to linker.
+ 
+ ;; lra is still unproven for ARC, so allow to fall back to reload with -mno-lra.
+-- 
+2.7.4
+
diff --git a/toolchain/gcc/patches/6.3.0/0062-ARC-define-SIZE_TYPE-and-PTRDIFF_TYPE-correctly.patch b/toolchain/gcc/patches/6.3.0/0062-ARC-define-SIZE_TYPE-and-PTRDIFF_TYPE-correctly.patch
new file mode 100644
index 0000000..018f843
--- /dev/null
+++ b/toolchain/gcc/patches/6.3.0/0062-ARC-define-SIZE_TYPE-and-PTRDIFF_TYPE-correctly.patch
@@ -0,0 +1,38 @@
+From bbabc467b57928ec8e1a6fabc4fd1f79421b20a1 Mon Sep 17 00:00:00 2001
+From: Vineet Gupta <vgupta at synopsys.com>
+Date: Wed, 2 Nov 2016 13:15:51 +0100
+Subject: [PATCH 62/89] [ARC] define SIZE_TYPE and PTRDIFF_TYPE correctly.
+
+This silences tons of -Wformat= warnings when building ARC Linux kernel
+with gcc 6.x (and restores the ARC gcc 4.8.x behaviour) which had
+similar fix.
+
+gcc/
+2016-11-02  Vineet Gupta  <vgupta at synopsys.com>
+
+	* config/arc/arc.h (SIZE_TYPE): Define as unsigned int.
+	(PTRDIFF_TYPE): Define as int.
+---
+ gcc/config/arc/arc.h | 4 ++--
+ 1 file changed, 2 insertions(+), 2 deletions(-)
+
+diff --git a/gcc/config/arc/arc.h b/gcc/config/arc/arc.h
+index 99c3e6b9b44f..e071946d8be5 100644
+--- a/gcc/config/arc/arc.h
++++ b/gcc/config/arc/arc.h
+@@ -282,10 +282,10 @@ if (GET_MODE_CLASS (MODE) == MODE_INT		\
+ #define DEFAULT_SIGNED_CHAR 0
+ 
+ #undef SIZE_TYPE
+-#define SIZE_TYPE "long unsigned int"
++#define SIZE_TYPE "unsigned int"
+ 
+ #undef PTRDIFF_TYPE
+-#define PTRDIFF_TYPE "long int"
++#define PTRDIFF_TYPE "int"
+ 
+ #undef WCHAR_TYPE
+ #define WCHAR_TYPE "int"
+-- 
+2.7.4
+
diff --git a/toolchain/gcc/patches/6.3.0/0063-ARC-HACK-Hard-check-for-the-LP-size-constraints.patch b/toolchain/gcc/patches/6.3.0/0063-ARC-HACK-Hard-check-for-the-LP-size-constraints.patch
new file mode 100644
index 0000000..7a54ac4
--- /dev/null
+++ b/toolchain/gcc/patches/6.3.0/0063-ARC-HACK-Hard-check-for-the-LP-size-constraints.patch
@@ -0,0 +1,38 @@
+From 634a22b3eef86b498ef4f011ceb7e64713090dfc Mon Sep 17 00:00:00 2001
+From: Claudiu Zissulescu <claziss at synopsys.com>
+Date: Wed, 2 Nov 2016 17:05:21 +0100
+Subject: [PATCH 63/89] [ARC] [HACK] Hard check for the LP size constraints.
+
+LP instruction can accept an s13 displacement.  However, the procedure
+which checks if the loop body fits is not complete.  For example, when
+the end of the loop is before the loop begin, then the size
+computation is totaly wrong.  As a solution, I check if the size
+computation has been done until we found a loop end to validate it,
+otherwise we will fall back on SR implementation.
+
+gcc/
+2016-11-02  Claudiu Zissulescu  <claziss at synopsys.com>
+
+	* config/arc/arc.md (doloop_begin_i): Check if size is computed
+	correctly.
+---
+ gcc/config/arc/arc.md | 3 +++
+ 1 file changed, 3 insertions(+)
+
+diff --git a/gcc/config/arc/arc.md b/gcc/config/arc/arc.md
+index a193745dc9ba..211a98dac72c 100644
+--- a/gcc/config/arc/arc.md
++++ b/gcc/config/arc/arc.md
+@@ -5005,6 +5005,9 @@
+       len = get_attr_length (scan);
+       size += len;
+     }
++    /* Check if we found the end of the loop.  If not go safe.  */
++    if (!scan)
++      size = 2048;
+   /* Try to verify that there are at least three instruction fetches
+      between the loop setup and the first encounter of the loop end.  */
+   for (scan = NEXT_INSN (insn); scan && n_insns < 3; scan = NEXT_INSN (scan))
+-- 
+2.7.4
+
diff --git a/toolchain/gcc/patches/6.3.0/0064-ARC-Fix-sub_n-pattern.patch b/toolchain/gcc/patches/6.3.0/0064-ARC-Fix-sub_n-pattern.patch
new file mode 100644
index 0000000..9988200
--- /dev/null
+++ b/toolchain/gcc/patches/6.3.0/0064-ARC-Fix-sub_n-pattern.patch
@@ -0,0 +1,29 @@
+From a75f253251b43b5a5927d8d72c547b2e2e694276 Mon Sep 17 00:00:00 2001
+From: Claudiu Zissulescu <claziss at synopsys.com>
+Date: Fri, 4 Nov 2016 11:46:59 +0100
+Subject: [PATCH 64/89] [ARC] Fix sub_n pattern.
+
+gcc/
+2016-11-04  Claudiu Zissulescu  <claziss at synopsys.com>
+
+	* config/arc/arc.md (sub_n): Use 'c' constraint letter.
+---
+ gcc/config/arc/arc.md | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+diff --git a/gcc/config/arc/arc.md b/gcc/config/arc/arc.md
+index 211a98dac72c..46eb6aff9aee 100644
+--- a/gcc/config/arc/arc.md
++++ b/gcc/config/arc/arc.md
+@@ -2944,7 +2944,7 @@
+ (define_insn "*sub_n"
+   [(set (match_operand:SI 0 "dest_reg_operand"                 "=Rcw,w,w")
+ 	(minus:SI (match_operand:SI 1 "nonmemory_operand"         "0,c,?Cal")
+-		  (mult:SI (match_operand:SI 2 "register_operand" "w,w,w")
++		  (mult:SI (match_operand:SI 2 "register_operand" "c,c,c")
+ 			   (match_operand:SI 3 "_2_4_8_operand" ""))))]
+   ""
+   "sub%z3%? %0,%1,%2"
+-- 
+2.7.4
+
diff --git a/toolchain/gcc/patches/6.3.0/0065-ARC-Make-mulsi-for-A700-pattern-commutative.patch b/toolchain/gcc/patches/6.3.0/0065-ARC-Make-mulsi-for-A700-pattern-commutative.patch
new file mode 100644
index 0000000..ebf6c45
--- /dev/null
+++ b/toolchain/gcc/patches/6.3.0/0065-ARC-Make-mulsi-for-A700-pattern-commutative.patch
@@ -0,0 +1,29 @@
+From 55c15dbadc2fe6f8c96b7965daf78a2c8a76325e Mon Sep 17 00:00:00 2001
+From: Claudiu Zissulescu <claziss at synopsys.com>
+Date: Thu, 10 Nov 2016 11:09:22 +0100
+Subject: [PATCH 65/89] [ARC] Make mulsi for A700 pattern commutative.
+
+gcc/
+2016-11-10  Claudiu Zissulescu  <claziss at synopsys.com>
+
+	* config/arc/arc.md (mulsi3_700): Make it commutative.
+---
+ gcc/config/arc/arc.md | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+diff --git a/gcc/config/arc/arc.md b/gcc/config/arc/arc.md
+index 46eb6aff9aee..59805f11076f 100644
+--- a/gcc/config/arc/arc.md
++++ b/gcc/config/arc/arc.md
+@@ -2084,7 +2084,7 @@
+ ; like MPY or MPYU.
+ (define_insn "mulsi3_700"
+  [(set (match_operand:SI 0 "mpy_dest_reg_operand"        "=Rcr,r,r,Rcr,r")
+-	(mult:SI (match_operand:SI 1 "register_operand"  " 0,c,0,0,c")
++	(mult:SI (match_operand:SI 1 "register_operand"  "%0,c,0,0,c")
+ 		 (match_operand:SI 2 "nonmemory_operand" "cL,cL,I,Cal,Cal")))]
+  "TARGET_ARC700_MPY"
+   "mpyu%? %0,%1,%2"
+-- 
+2.7.4
+
diff --git a/toolchain/gcc/patches/6.3.0/0066-ARC-Fix-LE-tests-for-nps400-variant.patch b/toolchain/gcc/patches/6.3.0/0066-ARC-Fix-LE-tests-for-nps400-variant.patch
new file mode 100644
index 0000000..a7c4190
--- /dev/null
+++ b/toolchain/gcc/patches/6.3.0/0066-ARC-Fix-LE-tests-for-nps400-variant.patch
@@ -0,0 +1,125 @@
+From 42125f5d57fe0b8a2a4f7ee8e78eaf28ec716542 Mon Sep 17 00:00:00 2001
+From: Andrew Burgess <andrew.burgess at embecosm.com>
+Date: Wed, 16 Nov 2016 12:55:43 +0100
+Subject: [PATCH 66/89] [ARC] Fix LE tests for nps400 variant.
+
+gcc/arc: New peephole2 and little endian arc test fixes
+
+Resolve some test failures introduced for little endian arc as a result
+of the recent arc/nps400 additions.
+
+There's a new peephole2 optimisation to merge together two zero_extracts
+in order that the movb instruction can be used.
+
+One of the test cases is extended so that the test does something
+meaningful in both big and little endian arc mode.
+
+Other tests have their expected results updated to reflect improvements
+in other areas of GCC.
+
+gcc/ChangeLog:
+
+ Andrew Burgess  <andrew.burgess at embecosm.com>
+
+	* config/arc/arc.md (movb peephole2): New peephole2 to merge two
+	zero_extract operations to allow a movb to occur.
+	* gcc.target/arc/movb-1.c: Update little endian arc results.
+	* gcc.target/arc/movb-2.c: Likewise.
+	* gcc.target/arc/movb-5.c: Likewise.
+	* gcc.target/arc/movh_cl-1.c: Extend test to cover little endian
+	arc.
+---
+ gcc/config/arc/arc.md                    | 14 ++++++++++++++
+ gcc/testsuite/gcc.target/arc/movb-1.c    |  2 +-
+ gcc/testsuite/gcc.target/arc/movb-2.c    |  2 +-
+ gcc/testsuite/gcc.target/arc/movb-5.c    |  2 +-
+ gcc/testsuite/gcc.target/arc/movh_cl-1.c | 11 +++++++++++
+ 5 files changed, 28 insertions(+), 3 deletions(-)
+
+diff --git a/gcc/config/arc/arc.md b/gcc/config/arc/arc.md
+index 59805f11076f..992a114f3a38 100644
+--- a/gcc/config/arc/arc.md
++++ b/gcc/config/arc/arc.md
+@@ -6141,6 +6141,20 @@
+   ""
+   [(set_attr "length" "0")])
+ 
++(define_peephole2
++  [(set (match_operand:SI 0 "register_operand" "")
++	(zero_extract:SI (match_dup 0)
++			 (match_operand:SI 1 "const_int_operand" "")
++			 (match_operand:SI 2 "const_int_operand" "")))
++   (set (zero_extract:SI (match_operand:SI 3 "register_operand" "")
++			 (match_dup 1)
++			 (match_dup 2))
++	(match_dup 0))]
++  "TARGET_NPS_BITOPS
++   && !reg_overlap_mentioned_p (operands[0], operands[3])"
++  [(set (zero_extract:SI (match_dup 3) (match_dup 1) (match_dup 2))
++	(zero_extract:SI (match_dup 0) (match_dup 1) (match_dup 2)))])
++
+ ;; include the arc-FPX instructions
+ (include "fpx.md")
+ 
+diff --git a/gcc/testsuite/gcc.target/arc/movb-1.c b/gcc/testsuite/gcc.target/arc/movb-1.c
+index 965fd66aa99c..37f3fd8b27c4 100644
+--- a/gcc/testsuite/gcc.target/arc/movb-1.c
++++ b/gcc/testsuite/gcc.target/arc/movb-1.c
+@@ -11,4 +11,4 @@ f (void)
+   bar.b = foo.b;
+ }
+ /* { dg-final { scan-assembler "movb\[ \t\]+r\[0-5\]+, *r\[0-5\]+, *r\[0-5\]+, *5, *3, *8" { target arceb-*-* } } } */
+-/* { dg-final { scan-assembler "movb\[ \t\]+r\[0-5\]+, *r\[0-5\]+, *r\[0-5\]+, *19, *21, *8" { target arc-*-* } } } */
++/* { dg-final { scan-assembler "movb\[ \t\]+r\[0-5\]+, *r\[0-5\]+, *r\[0-5\]+, *3, *5, *8" { target arc-*-* } } } */
+diff --git a/gcc/testsuite/gcc.target/arc/movb-2.c b/gcc/testsuite/gcc.target/arc/movb-2.c
+index 9bd6d4187fd3..1ac18d05e4c0 100644
+--- a/gcc/testsuite/gcc.target/arc/movb-2.c
++++ b/gcc/testsuite/gcc.target/arc/movb-2.c
+@@ -10,5 +10,5 @@ f (void)
+ {
+   bar.b = foo.b;
+ }
+-/* { dg-final { scan-assembler "movb\[ \t\]+r\[0-5\]+, *r\[0-5\]+, *r\[0-5\]+, *23, *23, *9" { target arc-*-* } } } */
++/* { dg-final { scan-assembler "movb\[ \t\]+r\[0-5\]+, *r\[0-5\]+, *r\[0-5\]+, *7, *7, *9" { target arc-*-* } } } */
+ /* { dg-final { scan-assembler "movb\[ \t\]+r\[0-5\]+, *r\[0-5\]+, *r\[0-5\]+, *0, *0, *9" { target arceb-*-* } } } */
+diff --git a/gcc/testsuite/gcc.target/arc/movb-5.c b/gcc/testsuite/gcc.target/arc/movb-5.c
+index 0bcdd1c7874c..c8159feb6032 100644
+--- a/gcc/testsuite/gcc.target/arc/movb-5.c
++++ b/gcc/testsuite/gcc.target/arc/movb-5.c
+@@ -10,5 +10,5 @@ f (void)
+ {
+   bar.b = foo.b;
+ }
+-/* { dg-final { scan-assembler "movb\[ \t\]+r\[0-5\]+, *r\[0-5\]+, *r\[0-5\]+, *23, *(23|7), *9" { target arc-*-* } } } */
++/* { dg-final { scan-assembler "movb\[ \t\]+r\[0-5\]+, *r\[0-5\]+, *r\[0-5\]+, *7, *7, *9" { target arc-*-* } } } */
+ /* { dg-final { scan-assembler "movb\[ \t\]+r\[0-5\]+, *r\[0-5\]+, *r\[0-5\]+, *0, *0, *9" { target arceb-*-* } } } */
+diff --git a/gcc/testsuite/gcc.target/arc/movh_cl-1.c b/gcc/testsuite/gcc.target/arc/movh_cl-1.c
+index 13c0f3434433..9c0036c1a3a8 100644
+--- a/gcc/testsuite/gcc.target/arc/movh_cl-1.c
++++ b/gcc/testsuite/gcc.target/arc/movh_cl-1.c
+@@ -11,6 +11,9 @@ struct thing
+     {
+       unsigned a : 1;
+       unsigned b : 1;
++      unsigned c : 28;
++      unsigned d : 1;
++      unsigned e : 1;
+     };
+   };
+ };
+@@ -25,4 +28,12 @@ blah ()
+   func (xx.raw);
+ }
+ 
++void
++woof ()
++{
++  struct thing xx;
++  xx.d = xx.e = 1;
++  func (xx.raw);
++}
++
+ /* { dg-final { scan-assembler "movh\.cl r\[0-9\]+,0xc0000000>>16" } } */
+-- 
+2.7.4
+
diff --git a/toolchain/gcc/patches/6.3.0/0067-ARC-Make-lp_count-reg-fix-for-ARC600.patch b/toolchain/gcc/patches/6.3.0/0067-ARC-Make-lp_count-reg-fix-for-ARC600.patch
new file mode 100644
index 0000000..b48cf73
--- /dev/null
+++ b/toolchain/gcc/patches/6.3.0/0067-ARC-Make-lp_count-reg-fix-for-ARC600.patch
@@ -0,0 +1,53 @@
+From 8f2a8a15e09af99256f43ad2b7d3b5de8f317421 Mon Sep 17 00:00:00 2001
+From: Claudiu Zissulescu <claziss at synopsys.com>
+Date: Mon, 21 Nov 2016 16:44:46 +0100
+Subject: [PATCH 67/89] [ARC] Make lp_count reg fix for ARC600.
+
+gcc/
+2016-11-21  Claudiu Zissulescu  <claziss at synopsys.com>
+
+	* config/arc/arc.h (TARGET_LP_WR_INTERLOCK): Delete.
+	* config/arc/arc.c (arc_conditional_register_usage): Remove
+	TARGET_LP_WR_INTERLOCK condition.
+---
+ gcc/config/arc/arc.c | 9 +++++----
+ gcc/config/arc/arc.h | 3 ---
+ 2 files changed, 5 insertions(+), 7 deletions(-)
+
+diff --git a/gcc/config/arc/arc.c b/gcc/config/arc/arc.c
+index 6500e3e21f05..7af55d351074 100644
+--- a/gcc/config/arc/arc.c
++++ b/gcc/config/arc/arc.c
+@@ -1626,10 +1626,11 @@ arc_conditional_register_usage (void)
+      However, we can't actually use this approach, because for ARC the
+      delay slot scheduling pass is active, which runs after
+      machine_dependent_reorg.  */
+-  if (TARGET_ARC600)
+-    CLEAR_HARD_REG_BIT (reg_class_contents[SIBCALL_REGS], LP_COUNT);
+-  else if (!TARGET_LP_WR_INTERLOCK)
+-    fixed_regs[LP_COUNT] = 1;
++  if (TARGET_ARC600_FAMILY)
++    {
++      CLEAR_HARD_REG_BIT (reg_class_contents[SIBCALL_REGS], LP_COUNT);
++      fixed_regs[LP_COUNT] = 1;
++    }
+   for (regno = 0; regno < FIRST_PSEUDO_REGISTER; regno++)
+     if (!call_used_regs[regno])
+       CLEAR_HARD_REG_BIT (reg_class_contents[SIBCALL_REGS], regno);
+diff --git a/gcc/config/arc/arc.h b/gcc/config/arc/arc.h
+index e071946d8be5..1d256ca13f60 100644
+--- a/gcc/config/arc/arc.h
++++ b/gcc/config/arc/arc.h
+@@ -1599,9 +1599,6 @@ enum
+ /* ARC600, ARC601 and ARC700 feature macro.  */
+ #define TARGET_ARCOMPACT_FAMILY				\
+   (TARGET_ARC600 || TARGET_ARC601 || TARGET_ARC700)
+-/* Loop count register can be read in very next instruction after has
+-   been written to by an ordinary instruction.  */
+-#define TARGET_LP_WR_INTERLOCK (!TARGET_ARC600_FAMILY)
+ 
+ /* FPU defines.  */
+ /* Any FPU support.  */
+-- 
+2.7.4
+
diff --git a/toolchain/gcc/patches/6.3.0/0068-ARC-Add-support-for-advanced-mpy-mac-instructions.patch b/toolchain/gcc/patches/6.3.0/0068-ARC-Add-support-for-advanced-mpy-mac-instructions.patch
new file mode 100644
index 0000000..5aa6c8d
--- /dev/null
+++ b/toolchain/gcc/patches/6.3.0/0068-ARC-Add-support-for-advanced-mpy-mac-instructions.patch
@@ -0,0 +1,376 @@
+From 9f35b6bc524f3ddb8b41ffde58c81d284931ad4e Mon Sep 17 00:00:00 2001
+From: Claudiu Zissulescu <claziss at synopsys.com>
+Date: Thu, 8 Dec 2016 11:59:07 +0100
+Subject: [PATCH 68/89] [ARC] Add support for advanced mpy/mac instructions.
+
+gcc/
+2016-12-08  Claudiu Zissulescu  <claziss at synopsys.com>
+
+	* config/arc/arc.c (arc_conditional_register_usage): Handle ACCL,
+	ACCH registers.
+	* config/arc/arc.md (mulsidi3): Use advanced mpy instructions when
+	available.
+	(umulsidi3): Likewise.
+	(mulsidi3_700): Disable this pattern when we have advanced mpy
+	instructions.
+	(umulsidi3_700): Likewise.
+	(maddsidi4): New pattern.
+	(macd, mac, mac_r, umaddsidi4, macdu, macu, macu_r): Likewise.
+	(mpyd_arcv2hs, mpyd_imm_arcv2hs, mpydu_arcv2hs): Likewise.
+	(mpydu_imm_arcv2hs): Likewise.
+	* config/arc/predicates.md (accl_operand): New predicate.
+---
+ gcc/config/arc/arc.c         |   7 +-
+ gcc/config/arc/arc.md        | 266 ++++++++++++++++++++++++++++++++++++++++++-
+ gcc/config/arc/predicates.md |   5 +
+ 3 files changed, 274 insertions(+), 4 deletions(-)
+
+diff --git a/gcc/config/arc/arc.c b/gcc/config/arc/arc.c
+index 7af55d351074..e7a20e8ce08e 100644
+--- a/gcc/config/arc/arc.c
++++ b/gcc/config/arc/arc.c
+@@ -1764,8 +1764,9 @@ arc_conditional_register_usage (void)
+   arc_regno_reg_class[PROGRAM_COUNTER_REGNO] = GENERAL_REGS;
+ 
+   /*ARCV2 Accumulator.  */
+-  if (TARGET_V2
+-      && (TARGET_FP_DP_FUSED || TARGET_FP_SP_FUSED))
++  if ((TARGET_V2
++       && (TARGET_FP_DP_FUSED || TARGET_FP_SP_FUSED))
++      || TARGET_PLUS_DMPY)
+   {
+     arc_regno_reg_class[ACCL_REGNO] = WRITABLE_CORE_REGS;
+     arc_regno_reg_class[ACCH_REGNO] = WRITABLE_CORE_REGS;
+@@ -1773,6 +1774,8 @@ arc_conditional_register_usage (void)
+     SET_HARD_REG_BIT (reg_class_contents[WRITABLE_CORE_REGS], ACCH_REGNO);
+     SET_HARD_REG_BIT (reg_class_contents[CHEAP_CORE_REGS], ACCL_REGNO);
+     SET_HARD_REG_BIT (reg_class_contents[CHEAP_CORE_REGS], ACCH_REGNO);
++    SET_HARD_REG_BIT (reg_class_contents[GENERAL_REGS], ACCL_REGNO);
++    SET_HARD_REG_BIT (reg_class_contents[GENERAL_REGS], ACCH_REGNO);
+     arc_hard_regno_mode_ok[ACC_REG_FIRST] = D_MODES;
+   }
+ }
+diff --git a/gcc/config/arc/arc.md b/gcc/config/arc/arc.md
+index 992a114f3a38..5e9dbf15f3a9 100644
+--- a/gcc/config/arc/arc.md
++++ b/gcc/config/arc/arc.md
+@@ -2114,6 +2114,18 @@
+   "TARGET_ANY_MPY"
+ "
+ {
++  if (TARGET_PLUS_MACD)
++    {
++     if (CONST_INT_P (operands[2]))
++       {
++	emit_insn (gen_mpyd_imm_arcv2hs (operands[0], operands[1], operands[2]));
++       }
++     else
++       {
++	emit_insn (gen_mpyd_arcv2hs (operands[0], operands[1], operands[2]));
++       }
++     DONE;
++    }
+   if (TARGET_MPY)
+     {
+       operands[2] = force_reg (SImode, operands[2]);
+@@ -2194,7 +2206,7 @@
+   [(set (match_operand:DI 0 "register_operand" "=&r")
+ 	(mult:DI (sign_extend:DI (match_operand:SI 1 "register_operand" "%c"))
+ 		 (sign_extend:DI (match_operand:SI 2 "extend_operand" "cL"))))]
+-  "TARGET_MPY"
++  "TARGET_MPY && !TARGET_PLUS_MACD"
+   "#"
+   "&& reload_completed"
+   [(const_int 0)]
+@@ -2347,6 +2359,18 @@
+ 		 (zero_extend:DI (match_operand:SI 2 "nonmemory_operand" ""))))]
+   ""
+ {
++  if (TARGET_PLUS_MACD)
++    {
++     if (CONST_INT_P (operands[2]))
++       {
++	emit_insn (gen_mpydu_imm_arcv2hs (operands[0], operands[1], operands[2]));
++       }
++     else
++       {
++	emit_insn (gen_mpydu_arcv2hs (operands[0], operands[1], operands[2]));
++       }
++     DONE;
++    }
+   if (TARGET_MPY)
+     {
+       operands[2] = force_reg (SImode, operands[2]);
+@@ -2437,7 +2461,7 @@
+   [(set (match_operand:DI 0 "dest_reg_operand" "=&r")
+ 	(mult:DI (zero_extend:DI (match_operand:SI 1 "register_operand" "%c"))
+ 		 (zero_extend:DI (match_operand:SI 2 "extend_operand" "cL"))))]
+-  "TARGET_MPY"
++  "TARGET_MPY && !TARGET_PLUS_MACD"
+   "#"
+   "reload_completed"
+   [(const_int 0)]
+@@ -6155,6 +6179,244 @@
+   [(set (zero_extract:SI (match_dup 3) (match_dup 1) (match_dup 2))
+ 	(zero_extract:SI (match_dup 0) (match_dup 1) (match_dup 2)))])
+ 
++;; MAC and DMPY instructions
++(define_insn_and_split "maddsidi4"
++  [(set (match_operand:DI 0 "register_operand" "=r")
++	(plus:DI
++	 (mult:DI
++	  (sign_extend:DI (match_operand:SI 1 "register_operand" "%r"))
++	  (sign_extend:DI (match_operand:SI 2 "extend_operand" "ri")))
++	 (match_operand:DI 3 "register_operand" "r")))]
++  "TARGET_PLUS_DMPY"
++  "#"
++  "TARGET_PLUS_DMPY && reload_completed"
++  [(const_int 0)]
++  "{
++   rtx acc_reg = gen_rtx_REG (DImode, ACC_REG_FIRST);
++   emit_move_insn (acc_reg, operands[3]);
++   if (TARGET_PLUS_MACD)
++     emit_insn (gen_macd (operands[0], operands[1], operands[2]));
++   else
++     {
++      emit_insn (gen_mac (operands[1], operands[2]));
++      emit_move_insn (operands[0], acc_reg);
++     }
++   DONE;
++   }"
++  [(set_attr "type" "multi")
++   (set_attr "length" "36")])
++
++(define_insn "macd"
++  [(set (match_operand:DI 0 "even_register_operand"	       "=Rcr,r,r")
++	(plus:DI
++	 (mult:DI
++	  (sign_extend:DI (match_operand:SI 1 "register_operand" "%0,c,c"))
++	  (sign_extend:DI (match_operand:SI 2 "extend_operand" " c,cI,Cal")))
++	 (reg:DI ARCV2_ACC)))
++   (set (reg:DI ARCV2_ACC)
++	(plus:DI
++	 (mult:DI (sign_extend:DI (match_dup 1))
++		  (sign_extend:DI (match_dup 2)))
++	 (reg:DI ARCV2_ACC)))]
++ "TARGET_PLUS_MACD"
++ "macd %0,%1,%2"
++  [(set_attr "length" "4,4,8")
++   (set_attr "type" "multi")
++   (set_attr "predicable" "yes,no,no")
++   (set_attr "cond" "canuse,nocond,nocond")])
++
++(define_insn "mac"
++  [(set (reg:DI ARCV2_ACC)
++	(plus:DI
++	 (mult:DI (sign_extend:DI (match_operand:SI 0 "register_operand" "%r,r"))
++		  (sign_extend:DI (match_operand:SI 1 "extend_operand" "rI,i")))
++	 (reg:DI ARCV2_ACC)))]
++ "TARGET_PLUS_DMPY"
++ "mac 0,%0,%1"
++  [(set_attr "length" "4,8")
++   (set_attr "type" "multi")
++   (set_attr "predicable" "no")
++   (set_attr "cond" "nocond")])
++
++(define_peephole2
++  [(set (reg:DI ARCV2_ACC)
++	(plus:DI
++	 (mult:DI (sign_extend:DI (match_operand:SI 0 "register_operand" ""))
++		  (sign_extend:DI (match_operand:SI 1 "extend_operand" "")))
++	 (reg:DI ARCV2_ACC)))
++   (set (match_operand:SI 2 "register_operand" "")
++	(match_operand:SI 3 "accl_operand" ""))]
++ "TARGET_PLUS_DMPY"
++ [(const_int 0)]
++ {
++  emit_insn (gen_mac_r (operands[2], operands[0], operands[1]));
++  DONE;
++ })
++
++(define_insn "mac_r"
++  [(set (match_operand:SI 0 "register_operand" "=r,r")
++	(truncate:SI
++	 (plus:DI
++	  (mult:DI (sign_extend:DI (match_operand:SI 1 "register_operand" "%r,r"))
++		   (sign_extend:DI (match_operand:SI 2 "extend_operand" "rI,i")))
++	  (reg:DI ARCV2_ACC))))
++   (clobber (reg:DI ARCV2_ACC))]
++ "TARGET_PLUS_DMPY"
++ "mac %0,%1,%2"
++  [(set_attr "length" "4,8")
++   (set_attr "type" "multi")
++   (set_attr "predicable" "no")
++   (set_attr "cond" "nocond")])
++
++(define_insn_and_split "umaddsidi4"
++  [(set (match_operand:DI 0 "register_operand" "=r")
++	(plus:DI
++	 (mult:DI
++	  (zero_extend:DI (match_operand:SI 1 "register_operand" "%r"))
++	  (zero_extend:DI (match_operand:SI 2 "extend_operand" "ri")))
++	 (match_operand:DI 3 "register_operand" "r")))]
++  "TARGET_PLUS_DMPY"
++  "#"
++  "TARGET_PLUS_DMPY && reload_completed"
++  [(const_int 0)]
++  "{
++   rtx acc_reg = gen_rtx_REG (DImode, ACC_REG_FIRST);
++   emit_move_insn (acc_reg, operands[3]);
++   if (TARGET_PLUS_MACD)
++     emit_insn (gen_macdu (operands[0], operands[1], operands[2]));
++   else
++     {
++      emit_insn (gen_macu (operands[1], operands[2]));
++      emit_move_insn (operands[0], acc_reg);
++     }
++   DONE;
++   }"
++  [(set_attr "type" "multi")
++   (set_attr "length" "36")])
++
++(define_insn "macdu"
++  [(set (match_operand:DI 0 "even_register_operand"	       "=Rcr,r,r")
++	(plus:DI
++	 (mult:DI
++	  (zero_extend:DI (match_operand:SI 1 "register_operand" "%0,c,c"))
++	  (zero_extend:DI (match_operand:SI 2 "extend_operand" " c,cI,i")))
++	 (reg:DI ARCV2_ACC)))
++   (set (reg:DI ARCV2_ACC)
++	(plus:DI
++	 (mult:DI (zero_extend:DI (match_dup 1))
++		  (zero_extend:DI (match_dup 2)))
++	 (reg:DI ARCV2_ACC)))]
++ "TARGET_PLUS_MACD"
++ "macdu %0,%1,%2"
++  [(set_attr "length" "4,4,8")
++   (set_attr "type" "multi")
++   (set_attr "predicable" "yes,no,no")
++   (set_attr "cond" "canuse,nocond,nocond")])
++
++(define_insn "macu"
++  [(set (reg:DI ARCV2_ACC)
++	(plus:DI
++	 (mult:DI (zero_extend:DI (match_operand:SI 0 "register_operand" "%r,r"))
++		  (zero_extend:DI (match_operand:SI 1 "extend_operand" "rI,i")))
++	 (reg:DI ARCV2_ACC)))]
++ "TARGET_PLUS_DMPY"
++ "macu 0,%0,%1"
++  [(set_attr "length" "4,8")
++   (set_attr "type" "multi")
++   (set_attr "predicable" "no")
++   (set_attr "cond" "nocond")])
++
++(define_peephole2
++  [(set (reg:DI ARCV2_ACC)
++	(plus:DI
++	 (mult:DI (zero_extend:DI (match_operand:SI 0 "register_operand" ""))
++		  (zero_extend:DI (match_operand:SI 1 "extend_operand" "")))
++	 (reg:DI ARCV2_ACC)))
++   (set (match_operand:SI 2 "register_operand" "")
++	(match_operand:SI 3 "accl_operand" ""))]
++ "TARGET_PLUS_DMPY"
++ [(const_int 0)]
++ {
++  emit_insn (gen_macu_r (operands[2], operands[0], operands[1]));
++  DONE;
++ })
++
++(define_insn "macu_r"
++  [(set (match_operand:SI 0 "register_operand" "=r,r")
++	(truncate:SI
++	 (plus:DI
++	  (mult:DI (zero_extend:DI (match_operand:SI 1 "register_operand" "%r,r"))
++		   (zero_extend:DI (match_operand:SI 2 "extend_operand" "rI,i")))
++	  (reg:DI ARCV2_ACC))))
++   (clobber (reg:DI ARCV2_ACC))]
++ "TARGET_PLUS_DMPY"
++ "macu %0,%1,%2"
++  [(set_attr "length" "4,8")
++   (set_attr "type" "multi")
++   (set_attr "predicable" "no")
++   (set_attr "cond" "nocond")])
++
++(define_insn "mpyd_arcv2hs"
++  [(set (match_operand:DI 0 "even_register_operand"			"=Rcr, r")
++	(mult:DI (sign_extend:DI (match_operand:SI 1 "register_operand"	 "  0, c"))
++		 (sign_extend:DI (match_operand:SI 2 "register_operand"	 "  c, c"))))
++   (set (reg:DI ARCV2_ACC)
++	(mult:DI
++	  (sign_extend:DI (match_dup 1))
++	  (sign_extend:DI (match_dup 2))))]
++  "TARGET_PLUS_MACD"
++  "mpyd%? %0,%1,%2"
++  [(set_attr "length" "4,4")
++  (set_attr "iscompact" "false")
++  (set_attr "type" "multi")
++  (set_attr "predicable" "yes,no")
++  (set_attr "cond" "canuse,nocond")])
++
++(define_insn "mpyd_imm_arcv2hs"
++  [(set (match_operand:DI 0 "even_register_operand"			"=Rcr, r,r,Rcr,	 r")
++	(mult:DI (sign_extend:DI (match_operand:SI 1 "register_operand"	 "  0, c,0,  0,	 c"))
++		 (match_operand 2		    "immediate_operand"	 "  L, L,I,Cal,Cal")))
++   (set (reg:DI ARCV2_ACC)
++	(mult:DI (sign_extend:DI (match_dup 1))
++		 (match_dup 2)))]
++  "TARGET_PLUS_MACD"
++  "mpyd%? %0,%1,%2"
++  [(set_attr "length" "4,4,4,8,8")
++  (set_attr "iscompact" "false")
++  (set_attr "type" "multi")
++  (set_attr "predicable" "yes,no,no,yes,no")
++  (set_attr "cond" "canuse,nocond,nocond,canuse_limm,nocond")])
++
++(define_insn "mpydu_arcv2hs"
++  [(set (match_operand:DI 0 "even_register_operand"			"=Rcr, r")
++	(mult:DI (zero_extend:DI (match_operand:SI 1 "register_operand"	 "  0, c"))
++		 (zero_extend:DI (match_operand:SI 2 "register_operand" "   c, c"))))
++   (set (reg:DI ARCV2_ACC)
++	(mult:DI (zero_extend:DI (match_dup 1))
++		 (zero_extend:DI (match_dup 2))))]
++  "TARGET_PLUS_MACD"
++  "mpydu%? %0,%1,%2"
++  [(set_attr "length" "4,4")
++  (set_attr "iscompact" "false")
++  (set_attr "type" "multi")
++  (set_attr "predicable" "yes,no")
++  (set_attr "cond" "canuse,nocond")])
++
++(define_insn "mpydu_imm_arcv2hs"
++  [(set (match_operand:DI 0 "even_register_operand"			"=Rcr, r,r,Rcr,	 r")
++	(mult:DI (zero_extend:DI (match_operand:SI 1 "register_operand"	 "  0, c,0,  0,	 c"))
++		 (match_operand 2		    "immediate_operand"	 "  L, L,I,Cal,Cal")))
++   (set (reg:DI ARCV2_ACC)
++	(mult:DI (zero_extend:DI (match_dup 1))
++		 (match_dup 2)))]
++  "TARGET_PLUS_MACD"
++  "mpydu%? %0,%1,%2"
++  [(set_attr "length" "4,4,4,8,8")
++  (set_attr "iscompact" "false")
++  (set_attr "type" "multi")
++  (set_attr "predicable" "yes,no,no,yes,no")
++  (set_attr "cond" "canuse,nocond,nocond,canuse_limm,nocond")])
++
+ ;; include the arc-FPX instructions
+ (include "fpx.md")
+ 
+diff --git a/gcc/config/arc/predicates.md b/gcc/config/arc/predicates.md
+index 5c95c207758d..5dae7534a20c 100644
+--- a/gcc/config/arc/predicates.md
++++ b/gcc/config/arc/predicates.md
+@@ -678,6 +678,11 @@
+   (and (match_code "reg")
+        (match_test "REGNO (op) == (TARGET_BIG_ENDIAN ? 58 : 59)")))
+ 
++(define_predicate "accl_operand"
++  (and (match_code "reg")
++       (match_test "REGNO (op) == (TARGET_BIG_ENDIAN ? 59 : 58)")
++       (match_test "TARGET_V2")))
++
+ ; Unfortunately, we can not allow a const_int_operand before reload, because
+ ; reload needs a non-void mode to guide it how to reload the inside of a
+ ; {sign_}extend.
+-- 
+2.7.4
+
diff --git a/toolchain/gcc/patches/6.3.0/0069-ARC-Fix-typo-dmpyh-pattern.patch b/toolchain/gcc/patches/6.3.0/0069-ARC-Fix-typo-dmpyh-pattern.patch
new file mode 100644
index 0000000..e53a06e
--- /dev/null
+++ b/toolchain/gcc/patches/6.3.0/0069-ARC-Fix-typo-dmpyh-pattern.patch
@@ -0,0 +1,29 @@
+From 29fb6afa2f9d6b9ccfe51398ff073b565e48a1ca Mon Sep 17 00:00:00 2001
+From: Claudiu Zissulescu <claziss at synopsys.com>
+Date: Thu, 8 Dec 2016 12:01:06 +0100
+Subject: [PATCH 69/89] [ARC] Fix typo dmpyh pattern
+
+gcc/
+2016-12-08  Claudiu Zissulescu  <claziss at synopsys.com>
+
+	* config/arc/simdext.md (dmpyh): Fix typo.
+---
+ gcc/config/arc/simdext.md | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+diff --git a/gcc/config/arc/simdext.md b/gcc/config/arc/simdext.md
+index 51869e367726..95e9d2c038ff 100644
+--- a/gcc/config/arc/simdext.md
++++ b/gcc/config/arc/simdext.md
+@@ -1544,7 +1544,7 @@
+ 	   (SE:SI (vec_select:HI (match_dup 1) (parallel [(const_int 1)])))
+ 	   (SE:SI (vec_select:HI (match_dup 2) (parallel [(const_int 1)])))))))]
+   "TARGET_PLUS_DMPY"
+-  "dmpy<V_US_suffix>%? %0, %1, %2"
++  "dmpyh<V_US_suffix>%? %0, %1, %2"
+   [(set_attr "length" "4")
+    (set_attr "type" "multi")
+    (set_attr "predicable" "yes,no")
+-- 
+2.7.4
+
diff --git a/toolchain/gcc/patches/6.3.0/0070-ARC-Differentiate-between-ARCv1-and-ARCv2-h-reg-clas.patch b/toolchain/gcc/patches/6.3.0/0070-ARC-Differentiate-between-ARCv1-and-ARCv2-h-reg-clas.patch
new file mode 100644
index 0000000..c5c1ab7
--- /dev/null
+++ b/toolchain/gcc/patches/6.3.0/0070-ARC-Differentiate-between-ARCv1-and-ARCv2-h-reg-clas.patch
@@ -0,0 +1,120 @@
+From 61a6f04014bfb4171fc26da5110343c47daff509 Mon Sep 17 00:00:00 2001
+From: Claudiu Zissulescu <claziss at synopsys.com>
+Date: Thu, 8 Dec 2016 16:30:39 +0100
+Subject: [PATCH 70/89] [ARC] Differentiate between ARCv1 and ARCv2 'h'-reg
+ class for CMP insns.
+
+gcc/
+2016-12-08  Claudiu Zissulescu  <claziss at synopsys.com>
+
+	* config/arc/arc.md (cmpsi_cc_insn_mixed): Use 'h' register
+	constraint.
+	(cmpsi_cc_c_insn): Likewise.
+	(cbranchsi4_scratch): Compute proper instruction length using
+	compact_hreg_operand.
+	* config/arc/predicates.md (compact_hreg_operand): New predicate.
+---
+ gcc/config/arc/arc.md        | 28 ++++++++++++++++------------
+ gcc/config/arc/predicates.md | 13 +++++++++++++
+ 2 files changed, 29 insertions(+), 12 deletions(-)
+
+diff --git a/gcc/config/arc/arc.md b/gcc/config/arc/arc.md
+index 5e9dbf15f3a9..b70bd20e2fe7 100644
+--- a/gcc/config/arc/arc.md
++++ b/gcc/config/arc/arc.md
+@@ -3439,15 +3439,16 @@
+ ;; modifed cc user if second, but not first operand is a compact register.
+ (define_insn "cmpsi_cc_insn_mixed"
+   [(set (reg:CC CC_REG)
+-	(compare:CC (match_operand:SI 0 "register_operand" "Rcq#q,  h, c, c,qRcq,c")
+-		    (match_operand:SI 1 "nonmemory_operand"   "cO,Cm1,cI,cL, Cal,Cal")))]
++	(compare:CC (match_operand:SI 0 "register_operand" "Rcq#q,Rcqq,  h, c, c,qRcq,c")
++		    (match_operand:SI 1 "nonmemory_operand"   "cO,  hO,Cm1,cI,cL, Cal,Cal")))]
+   ""
+   "cmp%? %0,%B1%&"
+   [(set_attr "type" "compare")
+-   (set_attr "iscompact" "true,true,false,false,true_limm,false")
+-   (set_attr "predicable" "no,no,no,yes,no,yes")
++   (set_attr "iscompact" "true,true,true,false,false,true_limm,false")
++   (set_attr "predicable" "no,no,no,no,yes,no,yes")
+    (set_attr "cond" "set")
+-   (set_attr "length" "*,*,4,4,*,8")])
++   (set_attr "length" "*,*,*,4,4,*,8")
++   (set_attr "cpu_facility" "av1,av2,*,*,*,*,*")])
+ 
+ (define_insn "*cmpsi_cc_zn_insn"
+   [(set (reg:CC_ZN CC_REG)
+@@ -3523,14 +3524,15 @@
+ 
+ (define_insn "*cmpsi_cc_c_insn"
+   [(set (reg:CC_C CC_REG)
+-	(compare:CC_C (match_operand:SI 0 "register_operand"  "Rcqq,  h, c,Rcqq,  c")
+-		      (match_operand:SI 1 "nonmemory_operand"   "cO,Cm1,cI, Cal,Cal")))]
++	(compare:CC_C (match_operand:SI 0 "register_operand"  "Rcqq,Rcqq,  h, c,Rcqq,  c")
++		      (match_operand:SI 1 "nonmemory_operand"   "cO,  hO,Cm1,cI, Cal,Cal")))]
+   ""
+   "cmp%? %0,%S1%&"
+   [(set_attr "type" "compare")
+-   (set_attr "iscompact" "true,true,false,true_limm,false")
++   (set_attr "iscompact" "true,true,true,false,true_limm,false")
+    (set_attr "cond" "set")
+-   (set_attr "length" "*,*,4,*,8")])
++   (set_attr "length" "*,*,*,4,*,8")
++   (set_attr "cpu_facility" "av1,av2,*,*,*,*")])
+ 
+ ;; Next come the scc insns.
+ 
+@@ -4821,7 +4823,7 @@
+        case 8: if (!brcc_nolimm_operator (operands[0], VOIDmode))
+ 		 return \"br%d0%* %1, %B2, %^%l3\";
+        case 6: case 10:
+-       case 12:return \"cmp%? %1, %B2\\n\\tb%d0%* %^%l3%&;br%d0 out of range\";
++       case 12:return \"cmp%? %1, %B2\\n\\tb%d0%* %^%l3%& ;br%d0 out of range\";
+        default: fprintf (stderr, \"unexpected length %d\\n\", get_attr_length (insn)); fflush (stderr); gcc_unreachable ();
+      }
+    "
+@@ -4851,13 +4853,15 @@
+ 		    (minus (const_int 244)
+ 			   (symbol_ref "get_attr_delay_slot_length (insn)"))))
+ 	   (const_int 4)
+-	   (match_operand:SI 1 "compact_register_operand" "")
++	   (and (match_operand:SI 1 "compact_register_operand" "")
++		(match_operand:SI 2 "compact_hreg_operand" ""))
+ 	   (const_int 6)]
+ 	  (const_int 8))]
+ 	 (cond [(and (ge (minus (match_dup 3) (pc)) (const_int -256))
+ 		     (le (minus (match_dup 3) (pc)) (const_int 244)))
+ 		(const_int 8)
+-		(match_operand:SI 1 "compact_register_operand" "")
++		(and (match_operand:SI 1 "compact_register_operand" "")
++		     (match_operand:SI 2 "compact_hreg_operand" ""))
+ 		(const_int 10)]
+ 	       (const_int 12))))
+    (set (attr "iscompact")
+diff --git a/gcc/config/arc/predicates.md b/gcc/config/arc/predicates.md
+index 5dae7534a20c..a6b81a147897 100644
+--- a/gcc/config/arc/predicates.md
++++ b/gcc/config/arc/predicates.md
+@@ -189,6 +189,19 @@
+   }
+ )
+ 
++(define_predicate "compact_hreg_operand"
++  (match_code "reg, subreg")
++  {
++     if ((GET_MODE (op) != mode) && (mode != VOIDmode))
++	 return 0;
++
++      return (GET_CODE (op) == REG)
++      && (REGNO (op) >= FIRST_PSEUDO_REGISTER
++		|| (TARGET_V2 && REGNO (op) <= 31 && REGNO (op) != 30)
++		|| !TARGET_V2);
++  }
++)
++
+ ;; Return true if OP is an acceptable memory operand for ARCompact
+ ;; 16-bit store instructions
+ (define_predicate "compact_store_memory_operand"
+-- 
+2.7.4
+
diff --git a/toolchain/gcc/patches/6.3.0/0071-ARC-Differentiate-between-ARCv1-and-ARCv2-h-reg-clas.patch b/toolchain/gcc/patches/6.3.0/0071-ARC-Differentiate-between-ARCv1-and-ARCv2-h-reg-clas.patch
new file mode 100644
index 0000000..90efbd9
--- /dev/null
+++ b/toolchain/gcc/patches/6.3.0/0071-ARC-Differentiate-between-ARCv1-and-ARCv2-h-reg-clas.patch
@@ -0,0 +1,89 @@
+From 81486ae68c06bded143b9510fb29e83f90edbd9b Mon Sep 17 00:00:00 2001
+From: Claudiu Zissulescu <claziss at synopsys.com>
+Date: Thu, 8 Dec 2016 16:33:54 +0100
+Subject: [PATCH 71/89] [ARC] Differentiate between ARCv1 and ARCv2 'h'-reg
+ class for ADD insns.
+
+gcc/
+2016-12-08  Claudiu Zissulescu  <claziss at synopsys.com>
+
+	* config/arc/arc.c (arc_output_addsi): Check for h-register class
+	when emitting short ADD instructions.
+---
+ gcc/config/arc/arc.c | 42 +++++++++++++++++++++++++++---------------
+ 1 file changed, 27 insertions(+), 15 deletions(-)
+
+diff --git a/gcc/config/arc/arc.c b/gcc/config/arc/arc.c
+index e7a20e8ce08e..e3bcfb883351 100644
+--- a/gcc/config/arc/arc.c
++++ b/gcc/config/arc/arc.c
+@@ -7706,6 +7706,10 @@ arc_output_addsi (rtx *operands, bool cond_p, bool output_p)
+   int short_p = (!cond_p && short_0 && satisfies_constraint_Rcq (operands[1]));
+   int ret = 0;
+ 
++#define REG_H_P(OP) (REG_P (OP) && ((TARGET_V2 && REGNO (OP) <= 31	\
++				     && REGNO (OP) != 30)		\
++				    || !TARGET_V2))
++
+ #define ADDSI_OUTPUT1(FORMAT) do {\
+   if (output_p) \
+     output_asm_insn (FORMAT, operands);\
+@@ -7728,32 +7732,40 @@ arc_output_addsi (rtx *operands, bool cond_p, bool output_p)
+ 	 but add1 r0,sp,35 doesn't.  */
+       && (!output_p || (get_attr_length (current_output_insn) & 2)))
+     {
++      /* Generate add_s a,b,c; add_s b,b,u7; add_s c,b,u3; add_s b,b,h
++	 patterns.  */
+       if (short_p
+-	  && (REG_P (operands[2])
+-	      ? (match || satisfies_constraint_Rcq (operands[2]))
+-	      : (unsigned) intval <= (match ? 127 : 7)))
+-	ADDSI_OUTPUT1 ("add%? %0,%1,%2");
+-      if (short_0 && REG_P (operands[1]) && match2)
+-	ADDSI_OUTPUT1 ("add%? %0,%2,%1");
++	  && ((REG_H_P (operands[2])
++	       && (match || satisfies_constraint_Rcq (operands[2])))
++	      || (CONST_INT_P (operands[2])
++		  && ((unsigned) intval <= (match ? 127 : 7)))))
++	ADDSI_OUTPUT1 ("add%? %0,%1,%2 ;1");
++
++      /* Generate add_s b,b,h patterns.  */
++      if (short_0 && match2 && REG_H_P (operands[1]))
++	ADDSI_OUTPUT1 ("add%? %0,%2,%1 ;2");
++
++      /* Generate add_s b,sp,u7; add_s sp,sp,u7 patterns.  */
+       if ((short_0 || REGNO (operands[0]) == STACK_POINTER_REGNUM)
+ 	  && REGNO (operands[1]) == STACK_POINTER_REGNUM && !(intval & ~124))
+-	ADDSI_OUTPUT1 ("add%? %0,%1,%2");
++	ADDSI_OUTPUT1 ("add%? %0,%1,%2 ;3");
+ 
+       if ((short_p && (unsigned) neg_intval <= (match ? 31 : 7))
+ 	  || (REGNO (operands[0]) == STACK_POINTER_REGNUM
+ 	      && match && !(neg_intval & ~124)))
+-	ADDSI_OUTPUT1 ("sub%? %0,%1,%n2");
++	ADDSI_OUTPUT1 ("sub%? %0,%1,%n2 ;4");
+ 
+-      if (REG_P(operands[0]) && REG_P(operands[1])
+-	  && (REGNO(operands[0]) <= 31) && (REGNO(operands[0]) == REGNO(operands[1]))
+-	  && CONST_INT_P (operands[2]) && ( (intval>= -1) && (intval <= 6)))
+-	ADDSI_OUTPUT1 ("add%? %0,%1,%2");
++      /* Generate add_s h,h,s3 patterns.  */
++      if (REG_H_P (operands[0]) && match && TARGET_V2
++	  && CONST_INT_P (operands[2]) && ((intval>= -1) && (intval <= 6)))
++	ADDSI_OUTPUT1 ("add%? %0,%1,%2 ;5");
+ 
+-      if (TARGET_CODE_DENSITY && REG_P(operands[0]) && REG_P(operands[1])
+-	  && ((REGNO(operands[0]) == 0) || (REGNO(operands[0]) == 1))
++      /* Generate add_s r0,b,u6; add_s r1,b,u6 patterns.  */
++      if (TARGET_CODE_DENSITY && REG_P (operands[0]) && REG_P (operands[1])
++	  && ((REGNO (operands[0]) == 0) || (REGNO (operands[0]) == 1))
+ 	  && satisfies_constraint_Rcq (operands[1])
+ 	  && satisfies_constraint_L (operands[2]))
+-	ADDSI_OUTPUT1 ("add%? %0,%1,%2 ;3");
++	ADDSI_OUTPUT1 ("add%? %0,%1,%2 ;6");
+     }
+ 
+   /* Now try to emit a 32 bit insn without long immediate.  */
+-- 
+2.7.4
+
diff --git a/toolchain/gcc/patches/6.3.0/0072-ARC-Allow-extension-core-registers-to-be-used-for-ad.patch b/toolchain/gcc/patches/6.3.0/0072-ARC-Allow-extension-core-registers-to-be-used-for-ad.patch
new file mode 100644
index 0000000..9584159
--- /dev/null
+++ b/toolchain/gcc/patches/6.3.0/0072-ARC-Allow-extension-core-registers-to-be-used-for-ad.patch
@@ -0,0 +1,60 @@
+From b435891f00b8e8d31a49876f7246ad22e054321c Mon Sep 17 00:00:00 2001
+From: Claudiu Zissulescu <claziss at synopsys.com>
+Date: Fri, 9 Dec 2016 13:29:51 +0100
+Subject: [PATCH 72/89] [ARC] Allow extension core registers to be used for
+ addresses.
+
+gcc/
+2016-12-09  Claudiu Zissulescu  <claziss at synopsys.com>
+
+	* config/arc/arc.h (REGNO_OK_FOR_BASE_P): Consider also extension
+	core registers.
+	(REG_OK_FOR_INDEX_P_NONSTRICT): Likewise.
+	(REG_OK_FOR_BASE_P_NONSTRICT): Likewise.
+---
+ gcc/config/arc/arc.h | 20 +++++++++-----------
+ 1 file changed, 9 insertions(+), 11 deletions(-)
+
+diff --git a/gcc/config/arc/arc.h b/gcc/config/arc/arc.h
+index 1d256ca13f60..92c1ce858ff2 100644
+--- a/gcc/config/arc/arc.h
++++ b/gcc/config/arc/arc.h
+@@ -611,7 +611,8 @@ extern enum reg_class arc_regno_reg_class[];
+ #define REGNO_OK_FOR_BASE_P(REGNO)					\
+   ((REGNO) < 29 || ((REGNO) == ARG_POINTER_REGNUM) || ((REGNO) == 63)	\
+    || ((unsigned) reg_renumber[REGNO] < 29)				\
+-   || ((unsigned) (REGNO) == (unsigned) arc_tp_regno))
++   || ((unsigned) (REGNO) == (unsigned) arc_tp_regno)			\
++   || (fixed_regs[REGNO] == 0 && IN_RANGE (REGNO, 32, 59)))
+ 
+ #define REGNO_OK_FOR_INDEX_P(REGNO) REGNO_OK_FOR_BASE_P(REGNO)
+ 
+@@ -893,18 +894,15 @@ extern int arc_initial_elimination_offset(int from, int to);
+ 
+ /* Nonzero if X is a hard reg that can be used as an index
+    or if it is a pseudo reg.  */
+-#define REG_OK_FOR_INDEX_P_NONSTRICT(X) \
+-((unsigned) REGNO (X) >= FIRST_PSEUDO_REGISTER || \
+- (unsigned) REGNO (X) < 29 || \
+- (unsigned) REGNO (X) == 63 || \
+- (unsigned) REGNO (X) == ARG_POINTER_REGNUM)
++#define REG_OK_FOR_INDEX_P_NONSTRICT(X)			\
++  ((unsigned) REGNO (X) >= FIRST_PSEUDO_REGISTER	\
++   || REGNO_OK_FOR_BASE_P (REGNO (X)))
++
+ /* Nonzero if X is a hard reg that can be used as a base reg
+    or if it is a pseudo reg.  */
+-#define REG_OK_FOR_BASE_P_NONSTRICT(X) \
+-((unsigned) REGNO (X) >= FIRST_PSEUDO_REGISTER || \
+- (unsigned) REGNO (X) < 29 || \
+- (unsigned) REGNO (X) == 63 || \
+- (unsigned) REGNO (X) == ARG_POINTER_REGNUM)
++#define REG_OK_FOR_BASE_P_NONSTRICT(X)			\
++  ((unsigned) REGNO (X) >= FIRST_PSEUDO_REGISTER	\
++   || REGNO_OK_FOR_BASE_P (REGNO (X)))
+ 
+ /* Nonzero if X is a hard reg that can be used as an index.  */
+ #define REG_OK_FOR_INDEX_P_STRICT(X) REGNO_OK_FOR_INDEX_P (REGNO (X))
+-- 
+2.7.4
+
diff --git a/toolchain/gcc/patches/6.3.0/0073-ARC-Make-D0-D1-double-regs-fix-when-not-used.patch b/toolchain/gcc/patches/6.3.0/0073-ARC-Make-D0-D1-double-regs-fix-when-not-used.patch
new file mode 100644
index 0000000..61c7189
--- /dev/null
+++ b/toolchain/gcc/patches/6.3.0/0073-ARC-Make-D0-D1-double-regs-fix-when-not-used.patch
@@ -0,0 +1,33 @@
+From 10c17115e6a75067cb05a4f9ad9b0047af2cb476 Mon Sep 17 00:00:00 2001
+From: Claudiu Zissulescu <claziss at synopsys.com>
+Date: Fri, 9 Dec 2016 13:33:44 +0100
+Subject: [PATCH 73/89] [ARC] Make D0, D1 double regs fix when not used.
+
+gcc/
+2016-12-09  Claudiu Zissulescu  <claziss at synopsys.com>
+
+	* config/arc/arc.c (arc_conditional_register_usage): Make D0, D1
+	double regs fix when not used.
+---
+ gcc/config/arc/arc.c | 5 +++++
+ 1 file changed, 5 insertions(+)
+
+diff --git a/gcc/config/arc/arc.c b/gcc/config/arc/arc.c
+index e3bcfb883351..27a198233381 100644
+--- a/gcc/config/arc/arc.c
++++ b/gcc/config/arc/arc.c
+@@ -1736,6 +1736,11 @@ arc_conditional_register_usage (void)
+       arc_regno_reg_class[42] = ALL_REGS;
+       arc_regno_reg_class[43] = ALL_REGS;
+ 
++      fixed_regs[40] = 1;
++      fixed_regs[41] = 1;
++      fixed_regs[42] = 1;
++      fixed_regs[43] = 1;
++
+       arc_hard_regno_mode_ok[40] = 0;
+       arc_hard_regno_mode_ok[42] = 0;
+ 
+-- 
+2.7.4
+
diff --git a/toolchain/gcc/patches/6.3.0/0074-ARC-Use-ACCL-ACCH-registers-whenever-they-are-availa.patch b/toolchain/gcc/patches/6.3.0/0074-ARC-Use-ACCL-ACCH-registers-whenever-they-are-availa.patch
new file mode 100644
index 0000000..3519835
--- /dev/null
+++ b/toolchain/gcc/patches/6.3.0/0074-ARC-Use-ACCL-ACCH-registers-whenever-they-are-availa.patch
@@ -0,0 +1,36 @@
+From 931d11c96f19ddfc27f3d11c04cd2a7831fa7499 Mon Sep 17 00:00:00 2001
+From: Claudiu Zissulescu <claziss at synopsys.com>
+Date: Fri, 9 Dec 2016 13:36:47 +0100
+Subject: [PATCH 74/89] [ARC] Use ACCL, ACCH registers whenever they are
+ available.
+
+gcc/
+2016-12-09  Claudiu Zissulescu  <claziss at synopsys.com>
+
+	* config/arc/arc.c (arc_conditional_register_usage): Use ACCL,
+	ACCH registers whenever they are available.
+---
+ gcc/config/arc/arc.c | 7 +++++++
+ 1 file changed, 7 insertions(+)
+
+diff --git a/gcc/config/arc/arc.c b/gcc/config/arc/arc.c
+index 27a198233381..111577eafa10 100644
+--- a/gcc/config/arc/arc.c
++++ b/gcc/config/arc/arc.c
+@@ -1781,6 +1781,13 @@ arc_conditional_register_usage (void)
+     SET_HARD_REG_BIT (reg_class_contents[CHEAP_CORE_REGS], ACCH_REGNO);
+     SET_HARD_REG_BIT (reg_class_contents[GENERAL_REGS], ACCL_REGNO);
+     SET_HARD_REG_BIT (reg_class_contents[GENERAL_REGS], ACCH_REGNO);
++    SET_HARD_REG_BIT (reg_class_contents[MPY_WRITABLE_CORE_REGS], ACCL_REGNO);
++    SET_HARD_REG_BIT (reg_class_contents[MPY_WRITABLE_CORE_REGS], ACCH_REGNO);
++
++     /* Allow the compiler to freely use them.  */
++    fixed_regs[ACCL_REGNO] = 0;
++    fixed_regs[ACCH_REGNO] = 0;
++
+     arc_hard_regno_mode_ok[ACC_REG_FIRST] = D_MODES;
+   }
+ }
+-- 
+2.7.4
+
diff --git a/toolchain/gcc/patches/6.3.0/0075-ARC-Avoid-use-of-hard-registers-before-reg-alloc.patch b/toolchain/gcc/patches/6.3.0/0075-ARC-Avoid-use-of-hard-registers-before-reg-alloc.patch
new file mode 100644
index 0000000..0ccffd2
--- /dev/null
+++ b/toolchain/gcc/patches/6.3.0/0075-ARC-Avoid-use-of-hard-registers-before-reg-alloc.patch
@@ -0,0 +1,236 @@
+From 99e3345f33d56c5a378f7181afa36961381ffcc6 Mon Sep 17 00:00:00 2001
+From: Claudiu Zissulescu <claziss at synopsys.com>
+Date: Mon, 12 Dec 2016 16:17:26 +0100
+Subject: [PATCH 75/89] [ARC] Avoid use of hard registers before reg-alloc.
+
+gcc/
+2016-12-12  Claudiu Zissulescu  <claziss at synopsys.com>
+
+	* config/arc/arc.md (mulsi3): Avoid use of hard registers before
+	reg-alloc when having mul64 or mul32x16 instructions.
+	(mulsidi3): Likewise.
+	(umulsidi3): Likewise.
+	(mulsi32x16): New pattern.
+	(mulsi64): Likewise.
+	(mulsidi64): Likewise.
+	(umulsidi64): Likewise.
+---
+ gcc/config/arc/arc.md | 145 +++++++++++++++++++++++++++++++++++---------------
+ 1 file changed, 101 insertions(+), 44 deletions(-)
+
+diff --git a/gcc/config/arc/arc.md b/gcc/config/arc/arc.md
+index b70bd20e2fe7..c2bcfb530ad7 100644
+--- a/gcc/config/arc/arc.md
++++ b/gcc/config/arc/arc.md
+@@ -1897,29 +1897,15 @@
+     }
+   else if (TARGET_MUL64_SET)
+     {
+-      emit_insn (gen_mulsi_600 (operands[1], operands[2],
+-				gen_mlo (), gen_mhi ()));
+-      emit_move_insn (operands[0], gen_mlo ());
+-      DONE;
++     operands[0] = force_reg (SImode, operands[0]);
++     emit_insn (gen_mulsi64 (operands[0], operands[1], operands[2]));
++     DONE;
+     }
+   else if (TARGET_MULMAC_32BY16_SET)
+     {
+-      if (immediate_operand (operands[2], SImode)
+-	  && INTVAL (operands[2]) >= 0
+-	  && INTVAL (operands[2]) <= 65535)
+-	{
+-	  emit_insn (gen_umul_600 (operands[1], operands[2],
+-				     gen_acc2 (), gen_acc1 ()));
+-	  emit_move_insn (operands[0], gen_acc2 ());
+-	  DONE;
+-	}
+-      operands[2] = force_reg (SImode, operands[2]);
+-      emit_insn (gen_umul_600 (operands[1], operands[2],
+-			       gen_acc2 (), gen_acc1 ()));
+-      emit_insn (gen_mac_600 (operands[1], operands[2],
+-			       gen_acc2 (), gen_acc1 ()));
+-      emit_move_insn (operands[0], gen_acc2 ());
+-      DONE;
++     operands[0] = force_reg (SImode, operands[0]);
++     emit_insn (gen_mulsi32x16 (operands[0], operands[1], operands[2]));
++     DONE;
+     }
+   else
+     {
+@@ -1931,6 +1917,34 @@
+     }
+ })
+ 
++(define_insn_and_split "mulsi32x16"
++ [(set (match_operand:SI 0 "register_operand"            "=w")
++	(mult:SI (match_operand:SI 1 "register_operand"  "%c")
++		 (match_operand:SI 2 "nonmemory_operand" "ci")))]
++ "TARGET_MULMAC_32BY16_SET"
++ "#"
++ "TARGET_MULMAC_32BY16_SET && reload_completed"
++ [(const_int 0)]
++ {
++  if (immediate_operand (operands[2], SImode)
++    && INTVAL (operands[2]) >= 0
++    && INTVAL (operands[2]) <= 65535)
++     {
++      emit_insn (gen_umul_600 (operands[1], operands[2],
++				       gen_acc2 (), gen_acc1 ()));
++      emit_move_insn (operands[0], gen_acc2 ());
++      DONE;
++     }
++   emit_insn (gen_umul_600 (operands[1], operands[2],
++				   gen_acc2 (), gen_acc1 ()));
++   emit_insn (gen_mac_600 (operands[1], operands[2],
++				   gen_acc2 (), gen_acc1 ()));
++   emit_move_insn (operands[0], gen_acc2 ());
++   DONE;
++  }
++ [(set_attr "type" "multi")
++  (set_attr "length" "8")])
++
+ ; mululw conditional execution without a LIMM clobbers an input register;
+ ; we'd need a different pattern to describe this.
+ ; To make the conditional execution valid for the LIMM alternative, we
+@@ -1968,6 +1982,23 @@
+    (set_attr "predicable" "no, no, yes")
+    (set_attr "cond" "nocond, canuse_limm, canuse")])
+ 
++(define_insn_and_split "mulsi64"
++ [(set (match_operand:SI 0 "register_operand"            "=w")
++	(mult:SI (match_operand:SI 1 "register_operand"  "%c")
++		 (match_operand:SI 2 "nonmemory_operand" "ci")))]
++ "TARGET_MUL64_SET"
++ "#"
++ "TARGET_MUL64_SET && reload_completed"
++  [(const_int 0)]
++{
++  emit_insn (gen_mulsi_600 (operands[1], operands[2],
++			gen_mlo (), gen_mhi ()));
++  emit_move_insn (operands[0], gen_mlo ());
++  DONE;
++}
++  [(set_attr "type" "multi")
++   (set_attr "length" "8")])
++
+ (define_insn "mulsi_600"
+   [(set (match_operand:SI 2 "mlo_operand" "")
+ 	(mult:SI (match_operand:SI 0 "register_operand"  "%Rcq#q,c,c,c")
+@@ -2112,8 +2143,7 @@
+ 	(mult:DI (sign_extend:DI (match_operand:SI 1 "register_operand" ""))
+ 		 (sign_extend:DI (match_operand:SI 2 "nonmemory_operand" ""))))]
+   "TARGET_ANY_MPY"
+-"
+-{
++  {
+   if (TARGET_PLUS_MACD)
+     {
+      if (CONST_INT_P (operands[2]))
+@@ -2144,17 +2174,29 @@
+       emit_insn (gen_mulsidi_600 (operands[0], operands[1], operands[2]));
+       DONE;
+     }
+-  else if (TARGET_MULMAC_32BY16_SET)
+-    {
+-      rtx result_hi = gen_highpart(SImode, operands[0]);
+-      rtx result_low = gen_lowpart(SImode, operands[0]);
++  operands[2] = force_reg (SImode, operands[2]);
++    })
++
++(define_insn_and_split "mulsidi64"
++  [(set (match_operand:DI 0 "register_operand" "=w")
++	(mult:DI (sign_extend:DI (match_operand:SI 1 "register_operand" "%c"))
++		 (sign_extend:DI (match_operand:SI 2 "extend_operand" "ci"))))]
++  "TARGET_MULMAC_32BY16_SET"
++  "#"
++  "TARGET_MULMAC_32BY16_SET && reload_completed"
++  [(const_int 0)]
++  {
++   rtx result_hi = gen_highpart (SImode, operands[0]);
++   rtx result_low = gen_lowpart (SImode, operands[0]);
++
++   emit_insn (gen_mul64_600 (operands[1], operands[2]));
++   emit_insn (gen_mac64_600 (result_hi, operands[1], operands[2]));
++   emit_move_insn (result_low, gen_acc2 ());
++   DONE;
++  }
++  [(set_attr "type" "multi")
++   (set_attr "length" "8")])
+ 
+-      emit_insn (gen_mul64_600 (operands[1], operands[2]));
+-      emit_insn (gen_mac64_600 (result_hi, operands[1], operands[2]));
+-      emit_move_insn (result_low, gen_acc2 ());
+-      DONE;
+-    }
+-}")
+ 
+ (define_insn "mul64_600"
+   [(set (reg:DI 56)
+@@ -2385,20 +2427,14 @@
+     }
+   else if (TARGET_MUL64_SET)
+     {
+-      emit_insn (gen_umulsidi_600 (operands[0], operands[1], operands[2]));
++     operands[2] = force_reg (SImode, operands[2]);
++     emit_insn (gen_umulsidi_600 (operands[0], operands[1], operands[2]));
+       DONE;
+     }
+   else if (TARGET_MULMAC_32BY16_SET)
+     {
+-      rtx result_hi = gen_reg_rtx (SImode);
+-      rtx result_low = gen_reg_rtx (SImode);
+-
+-      result_hi = gen_highpart(SImode , operands[0]);
+-      result_low = gen_lowpart(SImode , operands[0]);
+-
+-      emit_insn (gen_umul64_600 (operands[1], operands[2]));
+-      emit_insn (gen_umac64_600 (result_hi, operands[1], operands[2]));
+-      emit_move_insn (result_low, gen_acc2 ());
++     operands[2] = force_reg (SImode, operands[2]);
++     emit_insn (gen_umulsidi64 (operands[0], operands[1], operands[2]));
+       DONE;
+     }
+   else
+@@ -2411,6 +2447,29 @@
+     }
+ })
+ 
++(define_insn_and_split "umulsidi64"
++  [(set (match_operand:DI 0 "register_operand" "=w")
++	(mult:DI (zero_extend:DI (match_operand:SI 1 "register_operand" "%c"))
++		 (zero_extend:DI (match_operand:SI 2 "extend_operand" "ci"))))]
++  "TARGET_MULMAC_32BY16_SET"
++  "#"
++  "TARGET_MULMAC_32BY16_SET && reload_completed"
++  [(const_int 0)]
++  {
++   rtx result_hi;
++   rtx result_low;
++
++   result_hi = gen_highpart (SImode, operands[0]);
++   result_low = gen_lowpart (SImode, operands[0]);
++
++   emit_insn (gen_umul64_600 (operands[1], operands[2]));
++   emit_insn (gen_umac64_600 (result_hi, operands[1], operands[2]));
++   emit_move_insn (result_low, gen_acc2 ());
++   DONE;
++   }
++  [(set_attr "type" "multi")
++   (set_attr "length" "8")])
++
+ (define_insn "umul64_600"
+   [(set (reg:DI 56)
+ 	(mult:DI (zero_extend:DI (match_operand:SI 0 "register_operand"
+@@ -2454,8 +2513,6 @@
+    (set_attr "predicable" "no,no,yes")
+    (set_attr "cond" "nocond, canuse_limm, canuse")])
+ 
+-
+-
+ ;; DI <- DI(unsigned SI) * DI(unsigned SI)
+ (define_insn_and_split "umulsidi3_700"
+   [(set (match_operand:DI 0 "dest_reg_operand" "=&r")
+-- 
+2.7.4
+
diff --git a/toolchain/gcc/patches/6.3.0/0076-ARC-Allow-r30-to-be-used-by-the-reg-alloc.patch b/toolchain/gcc/patches/6.3.0/0076-ARC-Allow-r30-to-be-used-by-the-reg-alloc.patch
new file mode 100644
index 0000000..c0f0fa0
--- /dev/null
+++ b/toolchain/gcc/patches/6.3.0/0076-ARC-Allow-r30-to-be-used-by-the-reg-alloc.patch
@@ -0,0 +1,52 @@
+From 1d20df0c6321747a74b3e7132cc91954511aa840 Mon Sep 17 00:00:00 2001
+From: Claudiu Zissulescu <claziss at synopsys.com>
+Date: Mon, 12 Dec 2016 16:20:37 +0100
+Subject: [PATCH 76/89] [ARC] Allow r30 to be used by the reg-alloc.
+
+gcc/
+2016-12-12  Claudiu Zissulescu  <claziss at synopsys.com>
+
+	* config/arc/arc.c (arc_conditional_register_usage): Allow r30 to
+	be used by the reg-alloc.
+---
+ gcc/config/arc/arc.c | 9 ++++++++-
+ gcc/config/arc/arc.h | 3 ++-
+ 2 files changed, 10 insertions(+), 2 deletions(-)
+
+diff --git a/gcc/config/arc/arc.c b/gcc/config/arc/arc.c
+index 111577eafa10..56edc6fe9152 100644
+--- a/gcc/config/arc/arc.c
++++ b/gcc/config/arc/arc.c
+@@ -1530,7 +1530,14 @@ arc_conditional_register_usage (void)
+       /* For ARCv2 the core register set is changed.  */
+       strcpy (rname29, "ilink");
+       strcpy (rname30, "r30");
+-      fixed_regs[30] = call_used_regs[30] = 1;
++      call_used_regs[30] = 1;
++      fixed_regs[30] = 0;
++
++      arc_regno_reg_class[30] = WRITABLE_CORE_REGS;
++      SET_HARD_REG_BIT (reg_class_contents[WRITABLE_CORE_REGS], 30);
++      SET_HARD_REG_BIT (reg_class_contents[CHEAP_CORE_REGS], 30);
++      SET_HARD_REG_BIT (reg_class_contents[GENERAL_REGS], 30);
++      SET_HARD_REG_BIT (reg_class_contents[MPY_WRITABLE_CORE_REGS], 30);
+    }
+ 
+   if (TARGET_MUL64_SET)
+diff --git a/gcc/config/arc/arc.h b/gcc/config/arc/arc.h
+index 92c1ce858ff2..1f0f4989c239 100644
+--- a/gcc/config/arc/arc.h
++++ b/gcc/config/arc/arc.h
+@@ -612,7 +612,8 @@ extern enum reg_class arc_regno_reg_class[];
+   ((REGNO) < 29 || ((REGNO) == ARG_POINTER_REGNUM) || ((REGNO) == 63)	\
+    || ((unsigned) reg_renumber[REGNO] < 29)				\
+    || ((unsigned) (REGNO) == (unsigned) arc_tp_regno)			\
+-   || (fixed_regs[REGNO] == 0 && IN_RANGE (REGNO, 32, 59)))
++   || (fixed_regs[REGNO] == 0 && IN_RANGE (REGNO, 32, 59))		\
++   || ((REGNO) == 30 && fixed_regs[REGNO] == 0))
+ 
+ #define REGNO_OK_FOR_INDEX_P(REGNO) REGNO_OK_FOR_BASE_P(REGNO)
+ 
+-- 
+2.7.4
+
diff --git a/toolchain/gcc/patches/6.3.0/0077-ARC-Cxx-Fix-calling-multiple-inheritances.patch b/toolchain/gcc/patches/6.3.0/0077-ARC-Cxx-Fix-calling-multiple-inheritances.patch
new file mode 100644
index 0000000..31a1fff
--- /dev/null
+++ b/toolchain/gcc/patches/6.3.0/0077-ARC-Cxx-Fix-calling-multiple-inheritances.patch
@@ -0,0 +1,55 @@
+From 47ff89b9b4d7ae2f75208d9a683225213e4cd1f0 Mon Sep 17 00:00:00 2001
+From: Claudiu Zissulescu <claziss at synopsys.com>
+Date: Tue, 13 Dec 2016 11:48:36 +0100
+Subject: [PATCH 77/89] [ARC] [Cxx] Fix calling multiple inheritances.
+
+The TARGET_ASM_OUTPUT_MI_THUNK hook doesn't take into account the
+variant when we compile for PIC.
+
+gcc/
+2016-12-13  Claudiu Zissulescu  <claziss at synopsys.com>
+
+	* config/arc/arc.c (arc_output_mi_thunk): Emit PIC calls.
+---
+ gcc/config/arc/arc.c | 24 +++++++++++++++++++++---
+ 1 file changed, 21 insertions(+), 3 deletions(-)
+
+diff --git a/gcc/config/arc/arc.c b/gcc/config/arc/arc.c
+index 56edc6fe9152..0105d45da9eb 100644
+--- a/gcc/config/arc/arc.c
++++ b/gcc/config/arc/arc.c
+@@ -6765,10 +6765,28 @@ arc_output_mi_thunk (FILE *file, tree thunk ATTRIBUTE_UNUSED,
+   fnaddr = XEXP (DECL_RTL (function), 0);
+ 
+   if (arc_is_longcall_p (fnaddr))
+-    fputs ("\tj\t", file);
++    {
++      if (flag_pic)
++	{
++	  asm_fprintf (file, "\tld\t%s, [pcl, @",
++		       ARC_TEMP_SCRATCH_REG);
++	  assemble_name (file, XSTR (fnaddr, 0));
++	  fputs ("@gotpc]\n", file);
++	  asm_fprintf (file, "\tj\t[%s]", ARC_TEMP_SCRATCH_REG);
++	}
++      else
++	{
++	  fputs ("\tj\t@", file);
++	  assemble_name (file, XSTR (fnaddr, 0));
++	}
++    }
+   else
+-    fputs ("\tb\t", file);
+-  assemble_name (file, XSTR (fnaddr, 0));
++    {
++      fputs ("\tb\t@", file);
++      assemble_name (file, XSTR (fnaddr, 0));
++      if (flag_pic)
++	fputs ("@plt\n", file);
++    }
+   fputc ('\n', file);
+ }
+ 
+-- 
+2.7.4
+
diff --git a/toolchain/gcc/patches/6.3.0/0078-ARC-Addresses-can-use-long-immediate-for-offsets.patch b/toolchain/gcc/patches/6.3.0/0078-ARC-Addresses-can-use-long-immediate-for-offsets.patch
new file mode 100644
index 0000000..06b520f
--- /dev/null
+++ b/toolchain/gcc/patches/6.3.0/0078-ARC-Addresses-can-use-long-immediate-for-offsets.patch
@@ -0,0 +1,94 @@
+From f3278e85c837f78f2d1fea7226c55f9c1f95fda7 Mon Sep 17 00:00:00 2001
+From: Claudiu Zissulescu <claziss at synopsys.com>
+Date: Tue, 13 Dec 2016 13:22:21 +0100
+Subject: [PATCH 78/89] [ARC] Addresses can use long immediate for offsets.
+
+gcc/
+2016-12-13  Claudiu Zissulescu  <claziss at synopsys.com>
+
+	* config/arc/arc.c (LEGITIMATE_OFFSET_ADDRESS_P): Delete macro.
+	(legitimate_offset_address_p): New function.
+	(arc_legitimate_address_p): Use above function.
+---
+ gcc/config/arc/arc.c | 44 +++++++++++++++++++++++++++++++++++---------
+ 1 file changed, 35 insertions(+), 9 deletions(-)
+
+diff --git a/gcc/config/arc/arc.c b/gcc/config/arc/arc.c
+index 0105d45da9eb..1559c227da5f 100644
+--- a/gcc/config/arc/arc.c
++++ b/gcc/config/arc/arc.c
+@@ -77,13 +77,6 @@ static const char *arc_cpu_string = arc_cpu_name;
+ 		      ? 0 \
+ 		      : -(-GET_MODE_SIZE (MODE) | -4) >> 1)))
+ 
+-#define LEGITIMATE_OFFSET_ADDRESS_P(MODE, X, INDEX, STRICT) \
+-(GET_CODE (X) == PLUS			     \
+-  && RTX_OK_FOR_BASE_P (XEXP (X, 0), (STRICT)) \
+-  && ((INDEX && RTX_OK_FOR_INDEX_P (XEXP (X, 1), (STRICT)) \
+-       && GET_MODE_SIZE ((MODE)) <= 4) \
+-      || RTX_OK_FOR_OFFSET_P (MODE, XEXP (X, 1))))
+-
+ #define LEGITIMATE_SCALED_ADDRESS_P(MODE, X, STRICT) \
+ (GET_CODE (X) == PLUS \
+  && GET_CODE (XEXP (X, 0)) == MULT \
+@@ -285,6 +278,39 @@ bool arc_arc700 = false;
+ bool arc_arc600 = false;
+ bool arc_arc601 = false;
+ 
++/* Check for constructions like REG + OFFS, where OFFS can be a
++   register, an immediate or an long immediate. */
++
++static bool
++legitimate_offset_address_p (enum machine_mode mode, rtx x, bool index,
++			     bool strict)
++{
++  if (GET_CODE (x) != PLUS)
++    return false;
++
++  if (!RTX_OK_FOR_BASE_P (XEXP (x, 0), (strict)))
++    return false;
++
++  /* Check for: [Rx + small offset] or [Rx + Ry].  */
++  if (((index && RTX_OK_FOR_INDEX_P (XEXP (x, 1), (strict))
++	&& GET_MODE_SIZE ((mode)) <= 4)
++       || RTX_OK_FOR_OFFSET_P (mode, XEXP (x, 1))))
++    return true;
++
++  /* Check for [Rx + symbol].  */
++  if (!flag_pic
++      && (GET_CODE (XEXP (x, 1)) == SYMBOL_REF)
++      /* Avoid this type of address for double or larger modes.  */
++      && (GET_MODE_SIZE (mode) <= 4)
++      /* Avoid small data which ends in something like GP +
++	 symb at sda.  */
++      && (!SYMBOL_REF_SMALL_P (XEXP (x, 1))
++	  || TARGET_NO_SDATA_SET))
++    return true;
++
++  return false;
++}
++
+ /* Implements target hook vector_mode_supported_p.  */
+ 
+ static bool
+@@ -5932,7 +5958,7 @@ arc_legitimate_address_p (machine_mode mode, rtx x, bool strict)
+ {
+   if (RTX_OK_FOR_BASE_P (x, strict))
+      return true;
+-  if (LEGITIMATE_OFFSET_ADDRESS_P (mode, x, TARGET_INDEXED_LOADS, strict))
++  if (legitimate_offset_address_p (mode, x, TARGET_INDEXED_LOADS, strict))
+      return true;
+   if (LEGITIMATE_SCALED_ADDRESS_P (mode, x, strict))
+     return true;
+@@ -5973,7 +5999,7 @@ arc_legitimate_address_p (machine_mode mode, rtx x, bool strict)
+   if ((GET_CODE (x) == PRE_MODIFY || GET_CODE (x) == POST_MODIFY)
+       && GET_CODE (XEXP ((x), 1)) == PLUS
+       && rtx_equal_p (XEXP ((x), 0), XEXP (XEXP (x, 1), 0))
+-      && LEGITIMATE_OFFSET_ADDRESS_P (QImode, XEXP (x, 1),
++      && legitimate_offset_address_p (QImode, XEXP (x, 1),
+ 				      TARGET_AUTO_MODIFY_REG, strict))
+     return true;
+   return false;
+-- 
+2.7.4
+
diff --git a/toolchain/gcc/patches/6.3.0/0079-ARC-Add-support-for-naked-functions.patch b/toolchain/gcc/patches/6.3.0/0079-ARC-Add-support-for-naked-functions.patch
new file mode 100644
index 0000000..193673e
--- /dev/null
+++ b/toolchain/gcc/patches/6.3.0/0079-ARC-Add-support-for-naked-functions.patch
@@ -0,0 +1,512 @@
+From c959ad420906fb369b7d7fd0b7ca4e58231b496c Mon Sep 17 00:00:00 2001
+From: Claudiu Zissulescu <claziss at synopsys.com>
+Date: Tue, 13 Dec 2016 15:57:12 +0100
+Subject: [PATCH 79/89] [ARC] Add support for naked functions.
+
+gcc/
+2016-12-13  Claudiu Zissulescu  <claziss at synopsys.com>
+	    Andrew Burgess  <andrew.burgess at embecosm.com>
+
+	* config/arc/arc-protos.h (arc_compute_function_type): Change prototype.
+	(arc_return_address_register): New function.
+	* config/arc/arc.c (arc_handle_fndecl_attribute): New function.
+	(arc_handle_fndecl_attribute): Add naked attribute.
+	(TARGET_ALLOCATE_STACK_SLOTS_FOR_ARGS): Define.
+	(TARGET_WARN_FUNC_RETURN): Likewise.
+	(arc_allocate_stack_slots_for_args): New function.
+	(arc_warn_func_return): Likewise.
+	(machine_function): Change type fn_type.
+	(arc_compute_function_type): Consider new naked function type,
+	change function return type.
+	(arc_must_save_register): Adapt to handle new
+	arc_compute_function_type's return type.
+	(arc_expand_prologue): Likewise.
+	(arc_expand_epilogue): Likewise.
+	(arc_return_address_regs): Delete.
+	(arc_return_address_register): New function.
+	(arc_epilogue_uses): Use above function.
+	* config/arc/arc.h (arc_return_address_regs): Delete prototype.
+	(arc_function_type): Change encoding, add naked type.
+	(ARC_INTERRUPT_P): Change to handle the new encoding.
+	(ARC_FAST_INTERRUPT_P): Likewise.
+	(ARC_NORMAL_P): Define.
+	(ARC_NAKED_P): Likewise.
+	(arc_compute_function_type): Delete prototype.
+	* config/arc/arc.md (in_ret_delay_slot): Use
+	arc_return_address_register function.
+	(simple_return): Likewise.
+	(p_return_i): Likewise.
+
+gcc/testsuite
+2016-12-13  Claudiu Zissulescu  <claziss at synopsys.com>
+	    Andrew Burgess  <andrew.burgess at embecosm.com>
+
+	* gcc.target/arc/naked-1.c: New file.
+	* gcc.target/arc/naked-2.c: Likewise.
+---
+ gcc/config/arc/arc-protos.h            |   6 +-
+ gcc/config/arc/arc.c                   | 169 ++++++++++++++++++++++++---------
+ gcc/config/arc/arc.h                   |  40 +++++---
+ gcc/config/arc/arc.md                  |  10 +-
+ gcc/testsuite/gcc.target/arc/naked-1.c |  18 ++++
+ gcc/testsuite/gcc.target/arc/naked-2.c |  26 +++++
+ 6 files changed, 201 insertions(+), 68 deletions(-)
+ create mode 100644 gcc/testsuite/gcc.target/arc/naked-1.c
+ create mode 100644 gcc/testsuite/gcc.target/arc/naked-2.c
+
+diff --git a/gcc/config/arc/arc-protos.h b/gcc/config/arc/arc-protos.h
+index 7b8ceeaa13c1..83cf0f33aa78 100644
+--- a/gcc/config/arc/arc-protos.h
++++ b/gcc/config/arc/arc-protos.h
+@@ -45,12 +45,10 @@ extern void arc_expand_atomic_op (enum rtx_code, rtx, rtx, rtx, rtx, rtx);
+ extern void arc_split_compare_and_swap (rtx *);
+ extern void arc_expand_compare_and_swap (rtx *);
+ extern bool compact_memory_operand_p (rtx, machine_mode, bool, bool);
++extern int arc_return_address_register (unsigned int);
++extern unsigned int arc_compute_function_type (struct function *);
+ #endif /* RTX_CODE */
+ 
+-#ifdef TREE_CODE
+-extern enum arc_function_type arc_compute_function_type (struct function *);
+-#endif /* TREE_CODE */
+-
+ extern bool arc_ccfsm_branch_deleted_p (void);
+ extern void arc_ccfsm_record_branch_deleted (void);
+ 
+diff --git a/gcc/config/arc/arc.c b/gcc/config/arc/arc.c
+index 1559c227da5f..6f21fc372516 100644
+--- a/gcc/config/arc/arc.c
++++ b/gcc/config/arc/arc.c
+@@ -210,6 +210,7 @@ static int rgf_banked_register_count;
+ static int get_arc_condition_code (rtx);
+ 
+ static tree arc_handle_interrupt_attribute (tree *, tree, tree, int, bool *);
++static tree arc_handle_fndecl_attribute (tree *, tree, tree, int, bool *);
+ 
+ /* Initialized arc_attribute_table to NULL since arc doesnot have any
+    machine specific supported attributes.  */
+@@ -228,6 +229,9 @@ const struct attribute_spec arc_attribute_table[] =
+   /* And these functions are always known to reside within the 21 bit
+      addressing range of blcc.  */
+   { "short_call",   0, 0, false, true,  true,  NULL, false },
++  /* Function which are not having the prologue and epilogue generated
++     by the compiler.  */
++  { "naked", 0, 0, true, false, false, arc_handle_fndecl_attribute, false },
+   { NULL, 0, 0, false, false, false, NULL, false }
+ };
+ static int arc_comp_type_attributes (const_tree, const_tree);
+@@ -519,6 +523,12 @@ static void arc_finalize_pic (void);
+ #define TARGET_DIFFERENT_ADDR_DISPLACEMENT_P hook_bool_void_true
+ #define TARGET_SPILL_CLASS arc_spill_class
+ 
++#undef TARGET_ALLOCATE_STACK_SLOTS_FOR_ARGS
++#define TARGET_ALLOCATE_STACK_SLOTS_FOR_ARGS arc_allocate_stack_slots_for_args
++
++#undef TARGET_WARN_FUNC_RETURN
++#define TARGET_WARN_FUNC_RETURN arc_warn_func_return
++
+ #include "target-def.h"
+ 
+ #undef TARGET_ASM_ALIGNED_HI_OP
+@@ -1865,6 +1875,42 @@ arc_handle_interrupt_attribute (tree *, tree name, tree args, int,
+   return NULL_TREE;
+ }
+ 
++static tree
++arc_handle_fndecl_attribute (tree *node, tree name, tree args ATTRIBUTE_UNUSED,
++			     int flags ATTRIBUTE_UNUSED, bool *no_add_attrs)
++{
++  if (TREE_CODE (*node) != FUNCTION_DECL)
++    {
++      warning (OPT_Wattributes, "%qE attribute only applies to functions",
++	       name);
++      *no_add_attrs = true;
++    }
++
++  return NULL_TREE;
++}
++
++/* Implement `TARGET_ALLOCATE_STACK_SLOTS_FOR_ARGS' */
++
++static bool
++arc_allocate_stack_slots_for_args (void)
++{
++  /* Naked functions should not allocate stack slots for arguments.  */
++  unsigned int fn_type = arc_compute_function_type (cfun);
++
++  return !ARC_NAKED_P(fn_type);
++}
++
++/* Implement `TARGET_WARN_FUNC_RETURN'.  */
++
++static bool
++arc_warn_func_return (tree decl)
++{
++  struct function *func = DECL_STRUCT_FUNCTION (decl);
++  unsigned int fn_type = arc_compute_function_type (func);
++
++  return !ARC_NAKED_P (fn_type);
++}
++
+ /* Return zero if TYPE1 and TYPE are incompatible, one if they are compatible,
+    and two if they are nearly compatible (which causes a warning to be
+    generated).  */
+@@ -2368,7 +2414,7 @@ struct GTY (()) arc_frame_info
+ 
+ typedef struct GTY (()) machine_function
+ {
+-  enum arc_function_type fn_type;
++  unsigned int fn_type;
+   struct arc_frame_info frame_info;
+   /* To keep track of unalignment caused by short insns.  */
+   int unalign;
+@@ -2386,43 +2432,40 @@ typedef struct GTY (()) machine_function
+    The result is cached.  To reset the cache at the end of a function,
+    call with DECL = NULL_TREE.  */
+ 
+-enum arc_function_type
++unsigned int
+ arc_compute_function_type (struct function *fun)
+ {
+-  tree decl = fun->decl;
+-  tree a;
+-  enum arc_function_type fn_type = fun->machine->fn_type;
++  tree attr, decl = fun->decl;
++  unsigned int fn_type = fun->machine->fn_type;
+ 
+   if (fn_type != ARC_FUNCTION_UNKNOWN)
+     return fn_type;
+ 
+-  /* Assume we have a normal function (not an interrupt handler).  */
+-  fn_type = ARC_FUNCTION_NORMAL;
++  /* Check if it is a naked function.  */
++  if (lookup_attribute ("naked", DECL_ATTRIBUTES (decl)) != NULL_TREE)
++    fn_type |= ARC_FUNCTION_NAKED;
++  else
++    fn_type |= ARC_FUNCTION_NORMAL;
+ 
+   /* Now see if this is an interrupt handler.  */
+-  for (a = DECL_ATTRIBUTES (decl);
+-       a;
+-       a = TREE_CHAIN (a))
+-    {
+-      tree name = TREE_PURPOSE (a), args = TREE_VALUE (a);
+-
+-      if (name == get_identifier ("interrupt")
+-	  && list_length (args) == 1
+-	  && TREE_CODE (TREE_VALUE (args)) == STRING_CST)
+-	{
+-	  tree value = TREE_VALUE (args);
+-
+-	  if (!strcmp (TREE_STRING_POINTER (value), "ilink1")
+-	      || !strcmp (TREE_STRING_POINTER (value), "ilink"))
+-	    fn_type = ARC_FUNCTION_ILINK1;
+-	  else if (!strcmp (TREE_STRING_POINTER (value), "ilink2"))
+-	    fn_type = ARC_FUNCTION_ILINK2;
+-	  else if (!strcmp (TREE_STRING_POINTER (value), "firq"))
+-	    fn_type = ARC_FUNCTION_FIRQ;
+-	  else
+-	    gcc_unreachable ();
+-	  break;
+-	}
++  attr = lookup_attribute ("interrupt", DECL_ATTRIBUTES (decl));
++  if (attr != NULL_TREE)
++    {
++      tree value, args = TREE_VALUE (attr);
++
++      gcc_assert (list_length (args) == 1);
++      value = TREE_VALUE (args);
++      gcc_assert (TREE_CODE (value) == STRING_CST);
++
++      if (!strcmp (TREE_STRING_POINTER (value), "ilink1")
++	  || !strcmp (TREE_STRING_POINTER (value), "ilink"))
++	fn_type |= ARC_FUNCTION_ILINK1;
++      else if (!strcmp (TREE_STRING_POINTER (value), "ilink2"))
++	fn_type |= ARC_FUNCTION_ILINK2;
++      else if (!strcmp (TREE_STRING_POINTER (value), "firq"))
++	fn_type |= ARC_FUNCTION_FIRQ;
++      else
++	gcc_unreachable ();
+     }
+ 
+   return fun->machine->fn_type = fn_type;
+@@ -2458,7 +2501,7 @@ arc_compute_function_type (struct function *fun)
+ static bool
+ arc_must_save_register (int regno, struct function *func)
+ {
+-  enum arc_function_type fn_type = arc_compute_function_type (func);
++  unsigned int fn_type = arc_compute_function_type (func);
+   bool irq_auto_save_p = ((irq_ctrl_saved.irq_save_last_reg >= regno)
+ 			  && ARC_AUTO_IRQ_P (fn_type));
+   bool firq_auto_save_p = ARC_FAST_INTERRUPT_P (fn_type);
+@@ -2968,7 +3011,11 @@ arc_expand_prologue (void)
+      Change the stack layout so that we rather store a high register with the
+      PRE_MODIFY, thus enabling more short insn generation.)  */
+   int first_offset = 0;
+-  enum arc_function_type fn_type = arc_compute_function_type (cfun);
++  unsigned int fn_type = arc_compute_function_type (cfun);
++
++  /* Naked functions don't have prologue.  */
++  if (ARC_NAKED_P (fn_type))
++      return;
+ 
+   /* Compute total frame size.  */
+   size = arc_compute_frame_size ();
+@@ -3068,10 +3115,7 @@ void
+ arc_expand_epilogue (int sibcall_p)
+ {
+   int size;
+-  enum arc_function_type fn_type = arc_compute_function_type (cfun);
+-
+-  size = arc_compute_frame_size ();
+-
++  unsigned int fn_type = arc_compute_function_type (cfun);
+   unsigned int pretend_size = cfun->machine->frame_info.pretend_size;
+   unsigned int frame_size;
+   unsigned int size_to_deallocate;
+@@ -3081,6 +3125,16 @@ arc_expand_epilogue (int sibcall_p)
+   int millicode_p = cfun->machine->frame_info.millicode_end_reg > 0;
+   rtx insn;
+ 
++  /* Naked functions don't have epilogue.  */
++  if (ARC_NAKED_P (fn_type))
++    {
++      if (sibcall_p == FALSE)
++	emit_jump_insn (gen_simple_return ());
++      return;
++    }
++
++  size = arc_compute_frame_size ();
++
+   size_to_deallocate = size;
+ 
+   frame_size = size - (pretend_size +
+@@ -9820,37 +9874,60 @@ arc_can_follow_jump (const rtx_insn *follower, const rtx_insn *followee)
+   return true;
+ }
+ 
+-int arc_return_address_regs[5] =
+-  {0, RETURN_ADDR_REGNUM, ILINK1_REGNUM, ILINK2_REGNUM, ILINK1_REGNUM};
++/* Return the register number of the register holding the return address
++   for a function of type TYPE.  */
++
++int
++arc_return_address_register (unsigned int fn_type)
++{
++  int regno = 0;
++
++  if (ARC_INTERRUPT_P (fn_type))
++    {
++      if (((fn_type & ARC_FUNCTION_ILINK1) | ARC_FUNCTION_FIRQ) != 0)
++        regno = ILINK1_REGNUM;
++      else if ((fn_type & ARC_FUNCTION_ILINK2) != 0)
++        regno = ILINK2_REGNUM;
++      else
++        gcc_unreachable ();
++    }
++  else if (ARC_NORMAL_P (fn_type) || ARC_NAKED_P (fn_type))
++    regno = RETURN_ADDR_REGNUM;
+ 
+-/* Implement EPILOGUE__USES.
++  gcc_assert (regno != 0);
++  return regno;
++}
++
++/* Implement EPILOGUE_USES.
+    Return true if REGNO should be added to the deemed uses of the epilogue.
+ 
+-   We use the return address
+-   arc_return_address_regs[arc_compute_function_type (cfun)].  But
+-   also, we have to make sure all the register restore instructions
+-   are known to be live in interrupt functions, plus the blink
+-   register if it is clobbered by the isr.  */
++   We have to make sure all the register restore instructions are
++   known to be live in interrupt functions, plus the blink register if
++   it is clobbered by the isr.  */
+ 
+ bool
+ arc_epilogue_uses (int regno)
+ {
++  unsigned int fn_type;
++
+   if (regno == arc_tp_regno)
+     return true;
++
++  fn_type = arc_compute_function_type (cfun);
+   if (reload_completed)
+     {
+       if (ARC_INTERRUPT_P (cfun->machine->fn_type))
+ 	{
+ 	  if (!fixed_regs[regno])
+ 	    return true;
+-	  return ((regno == arc_return_address_regs[cfun->machine->fn_type])
++	  return ((regno == arc_return_address_register (fn_type))
+ 		  || (regno == RETURN_ADDR_REGNUM));
+ 	}
+       else
+ 	return regno == RETURN_ADDR_REGNUM;
+     }
+   else
+-    return regno == arc_return_address_regs[arc_compute_function_type (cfun)];
++    return regno == arc_return_address_register (fn_type);
+ }
+ 
+ /* Helper for EH_USES macro.  */
+diff --git a/gcc/config/arc/arc.h b/gcc/config/arc/arc.h
+index 1f0f4989c239..9fedac285010 100644
+--- a/gcc/config/arc/arc.h
++++ b/gcc/config/arc/arc.h
+@@ -1334,10 +1334,6 @@ do { \
+ #define ASM_OUTPUT_ALIGNED_DECL_LOCAL(STREAM, DECL, NAME, SIZE, ALIGNMENT) \
+   arc_asm_output_aligned_decl_local (STREAM, DECL, NAME, SIZE, ALIGNMENT, 0)
+ 
+-/* To translate the return value of arc_function_type into a register number
+-   to jump through for function return.  */
+-extern int arc_return_address_regs[5];
+-
+ /* Debugging information.  */
+ 
+ /* Generate DBX and DWARF debugging information.  */
+@@ -1473,22 +1469,38 @@ extern struct rtx_def *arc_compare_op0, *arc_compare_op1;
+ 
+ /* ARC function types.   */
+ enum arc_function_type {
+-  ARC_FUNCTION_UNKNOWN, ARC_FUNCTION_NORMAL,
++  /* No function should have the unknown type.  This value is used to
++   indicate the that function type has not yet been computed.  */
++  ARC_FUNCTION_UNKNOWN  = 0,
++
++  /* The normal function type indicates that the function has the
++   standard prologue and epilogue.  */
++  ARC_FUNCTION_NORMAL  = 1 << 0,
+   /* These are interrupt handlers.  The name corresponds to the register
+      name that contains the return address.  */
+-  ARC_FUNCTION_ILINK1, ARC_FUNCTION_ILINK2,
++  ARC_FUNCTION_ILINK1  = 1 << 1,
++  ARC_FUNCTION_ILINK2  = 1 << 2,
+   /* Fast interrupt is only available on ARCv2 processors.  */
+-  ARC_FUNCTION_FIRQ
++  ARC_FUNCTION_FIRQ    = 1 << 3,
++  /* The naked function type indicates that the function does not have
++   prologue or epilogue, and that no stack frame is available.  */
++  ARC_FUNCTION_NAKED   = 1 << 4
+ };
+-#define ARC_INTERRUPT_P(TYPE)						\
+-  (((TYPE) == ARC_FUNCTION_ILINK1) || ((TYPE) == ARC_FUNCTION_ILINK2)	\
+-   || ((TYPE) == ARC_FUNCTION_FIRQ))
+ 
+-#define ARC_FAST_INTERRUPT_P(TYPE) ((TYPE) == ARC_FUNCTION_FIRQ)
++/* Check if a function is an interrupt function.  */
++#define ARC_INTERRUPT_P(TYPE)					\
++  (((TYPE) & (ARC_FUNCTION_ILINK1 | ARC_FUNCTION_ILINK2		\
++	      | ARC_FUNCTION_FIRQ)) != 0)
++
++/* Check if a function is a fast interrupt function.  */
++#define ARC_FAST_INTERRUPT_P(TYPE) (((TYPE) & ARC_FUNCTION_FIRQ) != 0)
++
++/* Check if a function is normal, that is, has standard prologue and
++   epilogue.  */
++#define ARC_NORMAL_P(TYPE) (((TYPE) & ARC_FUNCTION_NORMAL) != 0)
+ 
+-/* Compute the type of a function from its DECL.  Needed for EPILOGUE_USES.  */
+-struct function;
+-extern enum arc_function_type arc_compute_function_type (struct function *);
++/* Check if a function is naked.  */
++#define ARC_NAKED_P(TYPE) (((TYPE) & ARC_FUNCTION_NAKED) != 0)
+ 
+ /* Called by crtstuff.c to make calls to function FUNCTION that are defined in
+    SECTION_OP, and then to switch back to text section.  */
+diff --git a/gcc/config/arc/arc.md b/gcc/config/arc/arc.md
+index c2bcfb530ad7..2c5e5f4a4c1d 100644
+--- a/gcc/config/arc/arc.md
++++ b/gcc/config/arc/arc.md
+@@ -503,8 +503,8 @@
+   (cond [(eq_attr "in_delay_slot" "false")
+ 	 (const_string "no")
+ 	 (match_test "regno_clobbered_p
+-			(arc_return_address_regs
+-			  [arc_compute_function_type (cfun)],
++			(arc_return_address_register
++			  (arc_compute_function_type (cfun)),
+ 			 insn, SImode, 1)")
+ 	 (const_string "no")]
+ 	(const_string "yes")))
+@@ -4774,7 +4774,8 @@
+ {
+   rtx reg
+     = gen_rtx_REG (Pmode,
+-		   arc_return_address_regs[arc_compute_function_type (cfun)]);
++		   arc_return_address_register (arc_compute_function_type
++						(cfun)));
+ 
+   if (TARGET_V2
+       && ARC_INTERRUPT_P (arc_compute_function_type (cfun)))
+@@ -4823,7 +4824,8 @@
+   xop[0] = operands[0];
+   xop[1]
+     = gen_rtx_REG (Pmode,
+-		   arc_return_address_regs[arc_compute_function_type (cfun)]);
++		   arc_return_address_register (arc_compute_function_type
++						(cfun)));
+ 
+   if (TARGET_PAD_RETURN)
+     arc_pad_return ();
+diff --git a/gcc/testsuite/gcc.target/arc/naked-1.c b/gcc/testsuite/gcc.target/arc/naked-1.c
+new file mode 100644
+index 000000000000..e8e4f7cd3152
+--- /dev/null
++++ b/gcc/testsuite/gcc.target/arc/naked-1.c
+@@ -0,0 +1,18 @@
++/* { dg-do compile } */
++/* { dg-options "-O0" } */
++/* Check that naked functions don't place arguments on the stack at
++   optimisation level '-O0'.  */
++extern void bar (int);
++
++void __attribute__((naked))
++foo (int n, int m)
++{
++  bar (n + m);
++}
++/* { dg-final { scan-assembler "\tbl @bar" } } */
++/* { dg-final { scan-assembler "\tj.* \\\[blink\\\]" } } */
++
++/* Look for things that would appear in a non-naked function, but which
++   should not appear in a naked function.  */
++/* { dg-final { scan-assembler-not "\tst.* " } } */
++/* { dg-final { scan-assembler-not "\tmov fp,sp" } } */
+diff --git a/gcc/testsuite/gcc.target/arc/naked-2.c b/gcc/testsuite/gcc.target/arc/naked-2.c
+new file mode 100644
+index 000000000000..7ada2cea6390
+--- /dev/null
++++ b/gcc/testsuite/gcc.target/arc/naked-2.c
+@@ -0,0 +1,26 @@
++/* { dg-do compile } */
++/* { dg-options "-O0" } */
++/* Check that naked functions don't place arguments on the stack at
++   optimisation level '-O0'.  */
++
++#if defined(__HS__) || defined(__EM__)
++# define ILINK "ilink"
++#else
++# define ILINK "ilink1"
++#endif
++
++extern void bar (int);
++
++void __attribute__((naked, interrupt(ILINK)))
++foo (int n, int m)
++{
++  bar (n + m);
++}
++/* { dg-final { scan-assembler "\tbl @bar" } } */
++/* { dg-final { scan-assembler "\trtie" { xfail { arc700 || arc6xx } } } } */
++/* { dg-final { scan-assembler "j.*\[ilink1\]" { xfail { archs || arcem } } } } */
++
++/* Look for things that would appear in a non-naked function, but which
++   should not appear in a naked function.  */
++/* { dg-final { scan-assembler-not "\tst.* " } } */
++/* { dg-final { scan-assembler-not "\tmov fp,sp" } } */
+-- 
+2.7.4
+
diff --git a/toolchain/gcc/patches/6.3.0/0080-ARC-Correct-and-update-ARC-builtin-documentation.patch b/toolchain/gcc/patches/6.3.0/0080-ARC-Correct-and-update-ARC-builtin-documentation.patch
new file mode 100644
index 0000000..cd59369
--- /dev/null
+++ b/toolchain/gcc/patches/6.3.0/0080-ARC-Correct-and-update-ARC-builtin-documentation.patch
@@ -0,0 +1,204 @@
+From 0b51f18bb0fa0e952fe2add82babb39457a29d47 Mon Sep 17 00:00:00 2001
+From: Claudiu Zissulescu <claziss at synopsys.com>
+Date: Wed, 14 Dec 2016 12:33:15 +0100
+Subject: [PATCH 80/89] [ARC] Correct and update ARC builtin documentation.
+
+gcc/
+2016-12-14  Claudiu Zissulescu  <claziss at synopsys.com>
+
+	* doc/extend.texi (ARC Built-in Functions): Correct and update ARC
+	builtin documentation.
+---
+ gcc/doc/extend.texi | 128 ++++++++++++++++++++++++++++++++++++++++++++++------
+ 1 file changed, 113 insertions(+), 15 deletions(-)
+
+diff --git a/gcc/doc/extend.texi b/gcc/doc/extend.texi
+index ee2715d7ea62..be6c66d0b739 100644
+--- a/gcc/doc/extend.texi
++++ b/gcc/doc/extend.texi
+@@ -11683,6 +11683,13 @@ brk
+ @end example
+ @end deftypefn
+ 
++ at deftypefn {Built-in Function}  void __builtin_arc_clri (unsigned int  @var{c})
++Only valid for ARCv2 architecture. Generates
++ at example
++clri  @var{c}
++ at end example
++ at end deftypefn
++
+ @deftypefn {Built-in Function} {unsigned int} __builtin_arc_core_read (unsigned int @var{regno})
+ The operand is the number of a register to be read.  Generates:
+ @example
+@@ -11711,6 +11718,15 @@ where the value in @var{dest} will be the result returned from the
+ built-in.
+ @end deftypefn
+ 
++ at deftypefn {Built-in Function} int __builtin_arc_ffs (int @var{a})
++Only valid for ARCv2 cpu cores and @option{-mnorm}.  Generates:
++ at example
++ffs  @var{dest}, @var{a}
++ at end example
++Where the value in @var{dest} will be the result returned from the
++built-in.
++ at end deftypefn
++
+ @deftypefn {Built-in Function} void __builtin_arc_flag (unsigned int @var{a})
+ Generates
+ @example
+@@ -11718,28 +11734,30 @@ flag  @var{a}
+ @end example
+ @end deftypefn
+ 
+- at deftypefn {Built-in Function} {unsigned int} __builtin_arc_lr (unsigned int @var{auxr})
+-The operand, @var{auxv}, is the address of an auxiliary register and
+-must be a compile time constant.  Generates:
++ at deftypefn {Built-in Function} int __builtin_arc_fls (int @var{a})
++Only valid for ARCv2 cpu cores and @option{-mnorm}.  Generates:
+ @example
+-lr  @var{dest}, [@var{auxr}]
++fls  @var{dest}, @var{a}
+ @end example
+ Where the value in @var{dest} will be the result returned from the
+ built-in.
+ @end deftypefn
+ 
+- at deftypefn {Built-in Function} void __builtin_arc_mul64 (int @var{a}, int @var{b})
+-Only available with @option{-mmul64}.  Generates:
++ at deftypefn {Built-in Function} void __builtin_arc_kflag (unsigned int @var{cc})
++Only valid for ARCv2 architecture. Generates:
+ @example
+-mul64  @var{a}, @var{b}
++kflag  @var{cc}
+ @end example
+ @end deftypefn
+ 
+- at deftypefn {Built-in Function} void __builtin_arc_mulu64 (unsigned int @var{a}, unsigned int @var{b})
+-Only available with @option{-mmul64}.  Generates:
++ at deftypefn {Built-in Function} {unsigned int} __builtin_arc_lr (unsigned int @var{auxr})
++The operand, @var{auxv}, is the address of an auxiliary register and
++must be a compile time constant.  Generates:
+ @example
+-mulu64  @var{a}, @var{b}
++lr  @var{dest}, [@var{auxr}]
+ @end example
++Where the value in @var{dest} will be the result returned from the
++built-in.
+ @end deftypefn
+ 
+ @deftypefn {Built-in Function} void __builtin_arc_nop (void)
+@@ -11778,6 +11796,13 @@ rtie
+ @end example
+ @end deftypefn
+ 
++ at deftypefn {Built-in Function}  void __builtin_arc_seti (int @var{c})
++Only valid for ARCv2 cpu cores.  Generates:
++ at example
++seti  @var{c}
++ at end example
++ at end deftypefn
++
+ @deftypefn {Built-in Function}  void __builtin_arc_sleep (int @var{a}
+ Generates:
+ @example
+@@ -11785,12 +11810,12 @@ sleep  @var{a}
+ @end example
+ @end deftypefn
+ 
+- at deftypefn {Built-in Function}  void __builtin_arc_sr (unsigned int @var{auxr}, unsigned int @var{val})
+-The first argument, @var{auxv}, is the address of an auxiliary
+-register, the second argument, @var{val}, is a compile time constant
+-to be written to the register.  Generates:
++ at deftypefn {Built-in Function}  void __builtin_arc_sr (unsigned int @var{val}, unsigned int @var{auxr})
++Store the 32-bit word held in source operand 1 (@var{val}) into the
++auxiliary register whose address is obtained from the source operand 2
++(@var{auxr}). Generates:
+ @example
+-sr  @var{auxr}, [@var{val}]
++sr  @var{val}, [@var{auxr}]
+ @end example
+ @end deftypefn
+ 
+@@ -12072,6 +12097,79 @@ void __builtin_arc_vst16_n (__v8hi, const int, const int, const int)
+ void __builtin_arc_vst32_n (__v8hi, const int, const int, const int)
+ @end example
+ 
++ at subsection ARCv2 SIMD Built-in Functions
++
++SIMD builtins provided by the compiler can be used to generate the
++vector instructions.  This section describes the available builtins
++and their usage in programs.  With the @option{-mmpy-option} option
++with values from 7 to 9, the compiler provides 32-bit or 64-bit vector
++types, which can be specified using the @code{vector_size}
++attribute. For example:
++ at example
++typedef int __v2hi   __attribute__((vector_size(4)));
++typedef short __v4hi __attribute__((vector_size(8)));
++typedef short __v2si __attribute__((vector_size(8)));
++ at end example
++
++The following take two @code{__v4hi} arguments and return a long long
++int. These builtins are available only for @option{-mpy-option=9}.
++ at example
++long long __builtin_arc_qmach (__v4hi, __v4hi);
++long long __builtin_arc_qmachu (__v4hi, __v4hi);
++long long __builtin_arc_qmpyh (__v4hi, __v4hi);
++long long __builtin_arc_qmpyhu (__v4hi, __v4hi);
++ at end example
++
++The following take two @code{__v2hi} arguments and return an
++int. These builtins are available only for @option{-mpy-option=7} or
++higher.
++ at example
++int __builtin_arc_dmach (__v2hi, __v2hi);
++int __builtin_arc_dmachu (__v2hi, __v2hi);
++int __builtin_arc_dmpyh (__v2hi, __v2hi);
++int __builtin_arc_dmpyhu (__v2hi, __v2hi);
++ at end example
++
++The following take a @code{__v2hi} argument, a @code{__v2si} argument
++and return a long long int. These builtins are available only for
++ at option{-mpy-option=9}.
++ at example
++long long __builtin_arc_dmacwh (__v2si, __v2hi);
++long long __builtin_arc_dmacwhu (__v2si, __v2hi);
++ at end example
++
++The following take two @code{__v2hi} arguments and return a
++ at code{__v2si}. These builtins are available only for @option{-mpy-option=8} or
++higher.
++ at example
++__v2si __builtin_arc_vmac2h (__v2hi, __v2hi);
++__v2si __builtin_arc_vmac2hu (__v2hi, __v2hi);
++__v2si __builtin_arc_vmpy2h (__v2hi, __v2hi);
++__v2si __builtin_arc_vmpy2hu (__v2hi, __v2hi);
++ at end example
++
++The following take two @code{__v2hi} arguments and return a
++ at code{__v2hi}. These builtins are available only for @option{-mpy-option=7} or
++higher.
++ at example
++__v2hi __builtin_arc_addsubv2hi3 (__v2hi, __v2hi);
++__v2hi __builtin_arc_subaddv2hi3 (__v2hi, __v2hi);
++ at end example
++
++The following take two @code{__v2si} arguments and return a
++ at code{__v2si}. These builtins are available only for @option{-mpy-option=9}.
++ at example
++__v2si __builtin_arc_addsubv2si3 (__v2si, __v2si);
++__v2si __builtin_arc_subaddv2si3 (__v2si, __v2si);
++ at end example
++
++The following take two @code{__v4hi} arguments and return a
++ at code{__v4hi}. These builtins are available only for @option{-mpy-option=9}.
++ at example
++__v4hi __builtin_arc_addsubv4hi3 (__v4hi, __v4hi);
++__v4hi __builtin_arc_subaddv4hi3 (__v4hi, __v4hi);
++ at end example
++
+ @node ARM iWMMXt Built-in Functions
+ @subsection ARM iWMMXt Built-in Functions
+ 
+-- 
+2.7.4
+
diff --git a/toolchain/gcc/patches/6.3.0/0081-ARC-Change-predicate-movv2hi-to-avoid-scaled-address.patch b/toolchain/gcc/patches/6.3.0/0081-ARC-Change-predicate-movv2hi-to-avoid-scaled-address.patch
new file mode 100644
index 0000000..800f2ff
--- /dev/null
+++ b/toolchain/gcc/patches/6.3.0/0081-ARC-Change-predicate-movv2hi-to-avoid-scaled-address.patch
@@ -0,0 +1,30 @@
+From ffd583d0b3bb5d6feb92541820aa73abaf188ed8 Mon Sep 17 00:00:00 2001
+From: Claudiu Zissulescu <claziss at gmail.com>
+Date: Sat, 17 Dec 2016 13:57:05 -0500
+Subject: [PATCH 81/89] [ARC] Change predicate movv2hi to avoid scaled
+ addresses.
+
+2016-12-17  Claudiu Zissulescu  <claziss at synopsys.com>
+
+	* config/arc/simdext.md (movv2hi_insn): Change predicate to avoid
+	scaled addresses.
+---
+ gcc/config/arc/simdext.md | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+diff --git a/gcc/config/arc/simdext.md b/gcc/config/arc/simdext.md
+index 95e9d2c038ff..f8285a1156a2 100644
+--- a/gcc/config/arc/simdext.md
++++ b/gcc/config/arc/simdext.md
+@@ -1320,7 +1320,7 @@
+    }")
+ 
+ (define_insn_and_split "*movv2hi_insn"
+-  [(set (match_operand:V2HI 0 "nonimmediate_operand" "=r,r,r,m")
++  [(set (match_operand:V2HI 0 "move_dest_operand" "=r,r,r,m")
+ 	(match_operand:V2HI 1 "general_operand"       "i,r,m,r"))]
+   "(register_operand (operands[0], V2HImode)
+     || register_operand (operands[1], V2HImode))"
+-- 
+2.7.4
+
diff --git a/toolchain/gcc/patches/6.3.0/0082-ARC-Update-non-commutative_binary_comparison-pattern.patch b/toolchain/gcc/patches/6.3.0/0082-ARC-Update-non-commutative_binary_comparison-pattern.patch
new file mode 100644
index 0000000..d12d8eb
--- /dev/null
+++ b/toolchain/gcc/patches/6.3.0/0082-ARC-Update-non-commutative_binary_comparison-pattern.patch
@@ -0,0 +1,63 @@
+From 9e505f78b4f50d6a5b89c2271073ca956a18f3dc Mon Sep 17 00:00:00 2001
+From: Claudiu Zissulescu <claziss at synopsys.com>
+Date: Tue, 20 Dec 2016 10:59:21 +0100
+Subject: [PATCH 82/89] [ARC] Update (non)commutative_binary_comparison
+ patterns.
+
+gcc/
+2016-12-20  Claudiu Zissulescu  <claziss at synopsys.com>
+
+	* config/arc/arc.md (commutative_binary_comparison): Remove 'I'
+	constraint. It is not valid for the pattern.
+	(noncommutative_binary_comparison): Likewise.
+---
+ gcc/config/arc/arc.md | 16 ++++++++--------
+ 1 file changed, 8 insertions(+), 8 deletions(-)
+
+diff --git a/gcc/config/arc/arc.md b/gcc/config/arc/arc.md
+index 2c5e5f4a4c1d..16f71b383b25 100644
+--- a/gcc/config/arc/arc.md
++++ b/gcc/config/arc/arc.md
+@@ -947,15 +947,15 @@
+   [(set (match_operand:CC_ZN 0 "cc_set_register" "")
+ 	(match_operator:CC_ZN 5 "zn_compare_operator"
+ 	  [(match_operator:SI 4 "commutative_operator"
+-	     [(match_operand:SI 1 "register_operand" "%c,c,c")
+-	      (match_operand:SI 2 "nonmemory_operand" "cL,I,?Cal")])
++	     [(match_operand:SI 1 "register_operand" "%c,c")
++	      (match_operand:SI 2 "nonmemory_operand" "cL,Cal")])
+ 	   (const_int 0)]))
+-   (clobber (match_scratch:SI 3 "=X,1,X"))]
++   (clobber (match_scratch:SI 3 "=X,X"))]
+   ""
+   "%O4.f 0,%1,%2"
+   [(set_attr "type" "compare")
+    (set_attr "cond" "set_zn")
+-   (set_attr "length" "4,4,8")])
++   (set_attr "length" "4,8")])
+ 
+ ; for flag setting 'add' instructions like if (a+b) { ...}
+ ; the combiner needs this pattern
+@@ -1049,15 +1049,15 @@
+   [(set (match_operand:CC_ZN 0 "cc_set_register" "")
+ 	(match_operator:CC_ZN 5 "zn_compare_operator"
+ 	  [(match_operator:SI 4 "noncommutative_operator"
+-	     [(match_operand:SI 1 "register_operand" "c,c,c")
+-	      (match_operand:SI 2 "nonmemory_operand" "cL,I,?Cal")])
++	     [(match_operand:SI 1 "register_operand" "c,c")
++	      (match_operand:SI 2 "nonmemory_operand" "cL,Cal")])
+ 	   (const_int 0)]))
+-   (clobber (match_scratch:SI 3 "=X,1,X"))]
++   (clobber (match_scratch:SI 3 "=X,X"))]
+   "TARGET_BARREL_SHIFTER || GET_CODE (operands[4]) == MINUS"
+   "%O4.f 0,%1,%2"
+   [(set_attr "type" "compare")
+    (set_attr "cond" "set_zn")
+-   (set_attr "length" "4,4,8")])
++   (set_attr "length" "4,8")])
+ 
+ (define_expand "bic_f_zn"
+   [(parallel
+-- 
+2.7.4
+
diff --git a/toolchain/gcc/patches/6.3.0/0083-ARC-Prevent-moving-stores-to-the-frame-before-the-st.patch b/toolchain/gcc/patches/6.3.0/0083-ARC-Prevent-moving-stores-to-the-frame-before-the-st.patch
new file mode 100644
index 0000000..74b0d8a
--- /dev/null
+++ b/toolchain/gcc/patches/6.3.0/0083-ARC-Prevent-moving-stores-to-the-frame-before-the-st.patch
@@ -0,0 +1,86 @@
+From cbd8e54244cd02bdcf4f1057be3ce96631f35ac3 Mon Sep 17 00:00:00 2001
+From: Claudiu Zissulescu <claziss at gmail.com>
+Date: Tue, 3 Jan 2017 12:06:28 -0500
+Subject: [PATCH 83/89] [ARC] Prevent moving stores to the frame before the
+ stack adjustment.
+
+If the stack pointer is needed, emit a special barrier that will prevent
+the scheduler from moving stores to the frame before the stack adjustment.
+
+2017-01-03  Claudiu Zissulescu  <claziss at synopsys.com>
+
+	* config/arc/arc.c (arc_expand_prologue): Emit a special barrier
+	to prevent store reordering.
+	* config/arc/arc.md (UNSPEC_ARC_STKTIE): Define.
+	(type): Add block type.
+	(stack_tie): Define special instruction to be used in
+	expand_prologue.
+---
+ gcc/config/arc/arc.c  | 10 +++++++++-
+ gcc/config/arc/arc.md | 15 ++++++++++++++-
+ 2 files changed, 23 insertions(+), 2 deletions(-)
+
+diff --git a/gcc/config/arc/arc.c b/gcc/config/arc/arc.c
+index 6f21fc372516..110556c0601d 100644
+--- a/gcc/config/arc/arc.c
++++ b/gcc/config/arc/arc.c
+@@ -3101,7 +3101,15 @@ arc_expand_prologue (void)
+   frame_size_to_allocate -= first_offset;
+   /* Allocate the stack frame.  */
+   if (frame_size_to_allocate > 0)
+-    frame_stack_add ((HOST_WIDE_INT) 0 - frame_size_to_allocate);
++    {
++      frame_stack_add ((HOST_WIDE_INT) 0 - frame_size_to_allocate);
++      /* If the frame pointer is needed, emit a special barrier that
++	 will prevent the scheduler from moving stores to the frame
++	 before the stack adjustment.  */
++      if (arc_frame_pointer_needed ())
++	emit_insn (gen_stack_tie (stack_pointer_rtx,
++				  hard_frame_pointer_rtx));
++    }
+ 
+   /* Setup the gp register, if needed.  */
+   if (crtl->uses_pic_offset_table)
+diff --git a/gcc/config/arc/arc.md b/gcc/config/arc/arc.md
+index 16f71b383b25..448157cf2b65 100644
+--- a/gcc/config/arc/arc.md
++++ b/gcc/config/arc/arc.md
+@@ -135,6 +135,7 @@
+   UNSPEC_ARC_VMAC2HU
+   UNSPEC_ARC_VMPY2H
+   UNSPEC_ARC_VMPY2HU
++  UNSPEC_ARC_STKTIE
+   ])
+ 
+ (define_c_enum "vunspec" [
+@@ -204,7 +205,7 @@
+    simd_vcompare, simd_vpermute, simd_vpack, simd_vpack_with_acc,
+    simd_valign, simd_valign_with_acc, simd_vcontrol,
+    simd_vspecial_3cycle, simd_vspecial_4cycle, simd_dma, mul16_em, div_rem,
+-   fpu"
++   fpu, block"
+   (cond [(eq_attr "is_sfunc" "yes")
+ 	 (cond [(match_test "!TARGET_LONG_CALLS_SET && (!TARGET_MEDIUM_CALLS || GET_CODE (PATTERN (insn)) != COND_EXEC)") (const_string "call")
+ 		(match_test "flag_pic") (const_string "sfunc")]
+@@ -6480,6 +6481,18 @@
+   (set_attr "predicable" "yes,no,no,yes,no")
+   (set_attr "cond" "canuse,nocond,nocond,canuse_limm,nocond")])
+ 
++(define_insn "stack_tie"
++  [(set (mem:BLK (scratch))
++	(unspec:BLK [(match_operand:SI 0 "register_operand" "rb")
++		     (match_operand:SI 1 "register_operand" "rb")]
++		    UNSPEC_ARC_STKTIE))]
++  ""
++  ""
++  [(set_attr "length" "0")
++   (set_attr "iscompact" "false")
++   (set_attr "type" "block")]
++  )
++
+ ;; include the arc-FPX instructions
+ (include "fpx.md")
+ 
+-- 
+2.7.4
+
diff --git a/toolchain/gcc/patches/6.3.0/0084-ARC-LRA-Fix-tests-asm-constraints.patch b/toolchain/gcc/patches/6.3.0/0084-ARC-LRA-Fix-tests-asm-constraints.patch
new file mode 100644
index 0000000..1821f1a
--- /dev/null
+++ b/toolchain/gcc/patches/6.3.0/0084-ARC-LRA-Fix-tests-asm-constraints.patch
@@ -0,0 +1,46 @@
+From db51a1a82ab3fcf294fa25cf74a9c98778a1505f Mon Sep 17 00:00:00 2001
+From: Claudiu Zissulescu <claziss at synopsys.com>
+Date: Mon, 9 Jan 2017 10:26:52 +0100
+Subject: [PATCH 84/89] [ARC] [LRA] Fix tests asm constraints.
+
+LRA doesn't like the 'X' constraint as used in our tests, remove it.
+
+gcc/testsuite
+2017-01-09  Claudiu Zissulescu  <claziss at synopsys.com>
+
+	* gcc.target/arc/mulsi3_highpart-1.c: Remove 'X' constraint.
+	* gcc.target/arc/mulsi3_highpart-2.c: Likewise.
+---
+ gcc/testsuite/gcc.target/arc/mulsi3_highpart-1.c | 2 +-
+ gcc/testsuite/gcc.target/arc/mulsi3_highpart-2.c | 2 +-
+ 2 files changed, 2 insertions(+), 2 deletions(-)
+
+diff --git a/gcc/testsuite/gcc.target/arc/mulsi3_highpart-1.c b/gcc/testsuite/gcc.target/arc/mulsi3_highpart-1.c
+index 57cb95b91fc1..5fd6c3603633 100644
+--- a/gcc/testsuite/gcc.target/arc/mulsi3_highpart-1.c
++++ b/gcc/testsuite/gcc.target/arc/mulsi3_highpart-1.c
+@@ -7,7 +7,7 @@
+ static int
+ id (int i)
+ {
+-  asm ("": "+Xr" (i));
++  asm ("": "+r" (i));
+   return i;
+ }
+ 
+diff --git a/gcc/testsuite/gcc.target/arc/mulsi3_highpart-2.c b/gcc/testsuite/gcc.target/arc/mulsi3_highpart-2.c
+index 287d96d4ee9a..6ec4bc5d8755 100644
+--- a/gcc/testsuite/gcc.target/arc/mulsi3_highpart-2.c
++++ b/gcc/testsuite/gcc.target/arc/mulsi3_highpart-2.c
+@@ -9,7 +9,7 @@
+ static int
+ id (int i)
+ {
+-  asm ("": "+Xr" (i));
++  asm ("": "+r" (i));
+   return i;
+ }
+ 
+-- 
+2.7.4
+
diff --git a/toolchain/gcc/patches/6.3.0/0085-ARC-Test-against-frame_pointer_needed-in-arc_can_eli.patch b/toolchain/gcc/patches/6.3.0/0085-ARC-Test-against-frame_pointer_needed-in-arc_can_eli.patch
new file mode 100644
index 0000000..b064139
--- /dev/null
+++ b/toolchain/gcc/patches/6.3.0/0085-ARC-Test-against-frame_pointer_needed-in-arc_can_eli.patch
@@ -0,0 +1,35 @@
+From 6747353bf09391477820fcbb17b224b70b6d7a81 Mon Sep 17 00:00:00 2001
+From: Claudiu Zissulescu <claziss at synopsys.com>
+Date: Mon, 9 Jan 2017 12:42:41 +0100
+Subject: [PATCH 85/89] [ARC] Test against frame_pointer_needed in
+ arc_can_eliminate.
+
+arc_can_eliminate is using arc_frmae_pointer_required() which is wrong
+as the frame_pointer_needed can be set on different conditions. Fix it
+by calling arc_frame_pointer_needed().
+
+gcc/
+2017-01-09  Claudiu Zissulescu  <claziss at synopsys.com>
+
+	* config/arc/arc.c (arc_can_eliminate): Test against
+	arc_frame_pointer_needed.
+---
+ gcc/config/arc/arc.c | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+diff --git a/gcc/config/arc/arc.c b/gcc/config/arc/arc.c
+index 110556c0601d..b49c54ffe470 100644
+--- a/gcc/config/arc/arc.c
++++ b/gcc/config/arc/arc.c
+@@ -4809,7 +4809,7 @@ arc_final_prescan_insn (rtx_insn *insn, rtx *opvec ATTRIBUTE_UNUSED,
+ static bool
+ arc_can_eliminate (const int from ATTRIBUTE_UNUSED, const int to)
+ {
+-  return to == FRAME_POINTER_REGNUM || !arc_frame_pointer_required ();
++  return ((to == FRAME_POINTER_REGNUM) || !arc_frame_pointer_needed ());
+ }
+ 
+ /* Define the offset between two registers, one to be eliminated, and
+-- 
+2.7.4
+
diff --git a/toolchain/gcc/patches/6.3.0/0086-ARC-Define-ADDITIONAL_REGISTER_NAMES.patch b/toolchain/gcc/patches/6.3.0/0086-ARC-Define-ADDITIONAL_REGISTER_NAMES.patch
new file mode 100644
index 0000000..e5469f9
--- /dev/null
+++ b/toolchain/gcc/patches/6.3.0/0086-ARC-Define-ADDITIONAL_REGISTER_NAMES.patch
@@ -0,0 +1,36 @@
+From 54f16230f5a74b7c2bb9015c480743b948a41192 Mon Sep 17 00:00:00 2001
+From: Claudiu Zissulescu <claziss at synopsys.com>
+Date: Mon, 9 Jan 2017 13:44:27 +0100
+Subject: [PATCH 86/89] [ARC] Define ADDITIONAL_REGISTER_NAMES.
+
+This macro is needed to be used with -ffixed-<reg> option, and inline asm.
+
+gcc/
+2017-01-09  Claudiu Zissulescu  <claziss at synopsys.com>
+
+	* config/arc/arc.h (ADDITIONAL_REGISTER_NAMES): Define.
+---
+ gcc/config/arc/arc.h | 7 +++++++
+ 1 file changed, 7 insertions(+)
+
+diff --git a/gcc/config/arc/arc.h b/gcc/config/arc/arc.h
+index 9fedac285010..6eafef494d19 100644
+--- a/gcc/config/arc/arc.h
++++ b/gcc/config/arc/arc.h
+@@ -1233,6 +1233,13 @@ extern char rname56[], rname57[], rname58[], rname59[];
+   "lp_start", "lp_end" \
+ }
+ 
++#define ADDITIONAL_REGISTER_NAMES		\
++{						\
++  {"ilink",  29},				\
++  {"r29",    29},				\
++  {"r30",    30}				\
++}
++
+ /* Entry to the insn conditionalizer.  */
+ #define FINAL_PRESCAN_INSN(INSN, OPVEC, NOPERANDS) \
+   arc_final_prescan_insn (INSN, OPVEC, NOPERANDS)
+-- 
+2.7.4
+
diff --git a/toolchain/gcc/patches/6.3.0/0087-ARC-LRA-Avoid-emitting-COND_EXEC-during-expand.patch b/toolchain/gcc/patches/6.3.0/0087-ARC-LRA-Avoid-emitting-COND_EXEC-during-expand.patch
new file mode 100644
index 0000000..0a49ff0
--- /dev/null
+++ b/toolchain/gcc/patches/6.3.0/0087-ARC-LRA-Avoid-emitting-COND_EXEC-during-expand.patch
@@ -0,0 +1,101 @@
+From dba9cdbce9cdad24dc956134d93cb362b38b8f00 Mon Sep 17 00:00:00 2001
+From: Claudiu Zissulescu <claziss at synopsys.com>
+Date: Tue, 10 Jan 2017 14:07:00 +0100
+Subject: [PATCH 87/89] [ARC] [LRA] Avoid emitting COND_EXEC during expand.
+
+Emmitting COND_EXEC rtxes during expand does not always work.
+
+gcc/
+2017-01-10  Claudiu Zissulescu  <claziss at synopsys.com>
+
+	* config/arc/arc.md (clzsi2): Expand to an arc_clzsi2 instruction
+	that also clobbers the CC register. The old expand code is moved
+	to ...
+	(*arc_clzsi2): ... here.
+	(ctzsi2): Expand to an arc_ctzsi2 instruction that also clobbers
+	the CC register. The old expand code is moved to ...
+	(arc_ctzsi2): ... here.
+---
+ gcc/config/arc/arc.md | 41 ++++++++++++++++++++++++++++++++++-------
+ 1 file changed, 34 insertions(+), 7 deletions(-)
+
+diff --git a/gcc/config/arc/arc.md b/gcc/config/arc/arc.md
+index 448157cf2b65..65b1ca330590 100644
+--- a/gcc/config/arc/arc.md
++++ b/gcc/config/arc/arc.md
+@@ -4449,9 +4449,21 @@
+    (set_attr "type" "two_cycle_core,two_cycle_core")])
+ 
+ (define_expand "clzsi2"
+-  [(set (match_operand:SI 0 "dest_reg_operand" "")
+-	(clz:SI (match_operand:SI 1 "register_operand" "")))]
++  [(parallel
++    [(set (match_operand:SI 0 "register_operand" "")
++	  (clz:SI (match_operand:SI 1 "register_operand" "")))
++     (clobber (match_dup 2))])]
++  "TARGET_NORM"
++  "operands[2] = gen_rtx_REG (CC_ZNmode, CC_REG);")
++
++(define_insn_and_split "*arc_clzsi2"
++  [(set (match_operand:SI 0 "register_operand" "=r")
++	(clz:SI (match_operand:SI 1 "register_operand" "r")))
++   (clobber (reg:CC_ZN CC_REG))]
+   "TARGET_NORM"
++  "#"
++  "reload_completed"
++  [(const_int 0)]
+ {
+   emit_insn (gen_norm_f (operands[0], operands[1]));
+   emit_insn
+@@ -4468,9 +4480,23 @@
+ })
+ 
+ (define_expand "ctzsi2"
+-  [(set (match_operand:SI 0 "register_operand" "")
+-	(ctz:SI (match_operand:SI 1 "register_operand" "")))]
++  [(match_operand:SI 0 "register_operand" "")
++   (match_operand:SI 1 "register_operand" "")]
+   "TARGET_NORM"
++  "
++  emit_insn (gen_arc_ctzsi2 (operands[0], operands[1]));
++  DONE;
++")
++
++(define_insn_and_split "arc_ctzsi2"
++  [(set (match_operand:SI 0 "register_operand" "=r")
++	(ctz:SI (match_operand:SI 1 "register_operand" "r")))
++   (clobber (reg:CC_ZN CC_REG))
++   (clobber (match_scratch:SI 2 "=&r"))]
++  "TARGET_NORM"
++  "#"
++  "reload_completed"
++  [(const_int 0)]
+ {
+   rtx temp = operands[0];
+ 
+@@ -4478,10 +4504,10 @@
+       || (REGNO (temp) < FIRST_PSEUDO_REGISTER
+ 	  && !TEST_HARD_REG_BIT (reg_class_contents[GENERAL_REGS],
+ 				 REGNO (temp))))
+-    temp = gen_reg_rtx (SImode);
++    temp = operands[2];
+   emit_insn (gen_addsi3 (temp, operands[1], constm1_rtx));
+   emit_insn (gen_bic_f_zn (temp, temp, operands[1]));
+-  emit_insn (gen_clrsbsi2 (temp, temp));
++  emit_insn (gen_clrsbsi2 (operands[0], temp));
+   emit_insn
+     (gen_rtx_COND_EXEC
+       (VOIDmode,
+@@ -4491,7 +4517,8 @@
+     (gen_rtx_COND_EXEC
+       (VOIDmode,
+        gen_rtx_GE (VOIDmode, gen_rtx_REG (CC_ZNmode, CC_REG), const0_rtx),
+-       gen_rtx_SET (operands[0], gen_rtx_MINUS (SImode, GEN_INT (31), temp))));
++       gen_rtx_SET (operands[0], gen_rtx_MINUS (SImode, GEN_INT (31),
++						operands[0]))));
+   DONE;
+ })
+ 
+-- 
+2.7.4
+
diff --git a/toolchain/gcc/patches/6.3.0/0088-ARC-Clean-up-building-warnings.patch b/toolchain/gcc/patches/6.3.0/0088-ARC-Clean-up-building-warnings.patch
new file mode 100644
index 0000000..ffd57a0
--- /dev/null
+++ b/toolchain/gcc/patches/6.3.0/0088-ARC-Clean-up-building-warnings.patch
@@ -0,0 +1,154 @@
+From 1a845926781d6db1793a0ee6979781dcb0becdaa Mon Sep 17 00:00:00 2001
+From: Claudiu Zissulescu <claziss at synopsys.com>
+Date: Tue, 10 Jan 2017 16:47:16 +0100
+Subject: [PATCH 88/89] [ARC] Clean up building warnings
+
+gcc/
+2017-01-10  Claudiu Zissulescu  <claziss at synopsys.com>
+
+	* config/arc/arc.md (movsi_set_cc_insn): Remove modes for operands
+	that are using special predicates.
+	(unary_comparison): Likewise.
+	(tst_bitfield_tst): Likewise.
+	(tst_bitfield_asr): Likewise.
+	(tst_bitfield): Likewise.
+	(commutative_binary_comparison): Likewise.
+	(noncommutative_binary_comparison): Likewise.
+	(scc_insn): Likewise.
+	(neg_scc_insn): Likewise.
+	(not_scc_insn): Likewise.
+	* config/arc/predicates.md (proper_comparison_operator): Make it
+	special.
+	(equality_comparison_operator): Likewise.
+---
+ gcc/config/arc/arc.md        | 28 ++++++++++++++--------------
+ gcc/config/arc/predicates.md |  4 ++--
+ 2 files changed, 16 insertions(+), 16 deletions(-)
+
+diff --git a/gcc/config/arc/arc.md b/gcc/config/arc/arc.md
+index 65b1ca330590..863c91b21975 100644
+--- a/gcc/config/arc/arc.md
++++ b/gcc/config/arc/arc.md
+@@ -782,8 +782,8 @@
+   [(set_attr "type" "store")])
+ 
+ (define_insn_and_split "*movsi_set_cc_insn"
+-  [(set (match_operand:CC_ZN 2 "cc_set_register" "")
+-	(match_operator:CC_ZN 3 "zn_compare_operator"
++  [(set (match_operand 2 "cc_set_register" "")
++	(match_operator 3 "zn_compare_operator"
+ 	  [(match_operand:SI 1 "nonmemory_operand" "cI,cL,Cal") (const_int 0)]))
+    (set (match_operand:SI 0 "register_operand" "=w,w,w")
+ 	(match_dup 1))]
+@@ -799,8 +799,8 @@
+    (set_attr "length" "4,4,8")])
+ 
+ (define_insn "unary_comparison"
+-  [(set (match_operand:CC_ZN 0 "cc_set_register" "")
+-	(match_operator:CC_ZN 3 "zn_compare_operator"
++  [(set (match_operand 0 "cc_set_register" "")
++	(match_operator 3 "zn_compare_operator"
+ 	  [(match_operator:SI 2 "unary_operator"
+ 	     [(match_operand:SI 1 "register_operand" "c")])
+ 	   (const_int 0)]))]
+@@ -891,7 +891,7 @@
+ ; so we rather use an extra pattern for tst;
+ ; since this is about constants, reload shouldn't care.
+ (define_insn "*tst_bitfield_tst"
+-  [(set (match_operand:CC_ZN 0 "cc_set_register" "")
++  [(set (match_operand 0 "cc_set_register" "")
+ 	(match_operator 4 "zn_compare_operator"
+ 	  [(zero_extract:SI
+ 	     (match_operand:SI 1 "register_operand"  "c")
+@@ -909,7 +909,7 @@
+ 
+ ; Likewise for asr.f.
+ (define_insn "*tst_bitfield_asr"
+-  [(set (match_operand:CC_ZN 0 "cc_set_register" "")
++  [(set (match_operand 0 "cc_set_register" "")
+ 	(match_operator 4 "zn_compare_operator"
+ 	  [(zero_extract:SI
+ 	     (match_operand:SI 1 "register_operand"  "c")
+@@ -924,7 +924,7 @@
+    (set_attr "length" "4")])
+ 
+ (define_insn "*tst_bitfield"
+-  [(set (match_operand:CC_ZN 0 "cc_set_register" "")
++  [(set (match_operand 0 "cc_set_register" "")
+ 	(match_operator 5 "zn_compare_operator"
+ 	  [(zero_extract:SI
+ 	     (match_operand:SI 1 "register_operand" "%Rcqq,c,  c,Rrq,c")
+@@ -945,8 +945,8 @@
+    (set_attr "length" "*,4,4,4,8")])
+ 
+ (define_insn "*commutative_binary_comparison"
+-  [(set (match_operand:CC_ZN 0 "cc_set_register" "")
+-	(match_operator:CC_ZN 5 "zn_compare_operator"
++  [(set (match_operand 0 "cc_set_register" "")
++	(match_operator 5 "zn_compare_operator"
+ 	  [(match_operator:SI 4 "commutative_operator"
+ 	     [(match_operand:SI 1 "register_operand" "%c,c")
+ 	      (match_operand:SI 2 "nonmemory_operand" "cL,Cal")])
+@@ -1047,8 +1047,8 @@
+    (set_attr "length" "4,4,8")])
+ 
+ (define_insn "*noncommutative_binary_comparison"
+-  [(set (match_operand:CC_ZN 0 "cc_set_register" "")
+-	(match_operator:CC_ZN 5 "zn_compare_operator"
++  [(set (match_operand 0 "cc_set_register" "")
++	(match_operator 5 "zn_compare_operator"
+ 	  [(match_operator:SI 4 "noncommutative_operator"
+ 	     [(match_operand:SI 1 "register_operand" "c,c")
+ 	      (match_operand:SI 2 "nonmemory_operand" "cL,Cal")])
+@@ -3641,7 +3641,7 @@
+ 
+ (define_insn_and_split "*scc_insn"
+   [(set (match_operand:SI 0 "dest_reg_operand" "=w")
+-	(match_operator:SI 1 "proper_comparison_operator" [(reg CC_REG) (const_int 0)]))]
++	(match_operator 1 "proper_comparison_operator" [(reg CC_REG) (const_int 0)]))]
+   ""
+   "#"
+   "reload_completed"
+@@ -3664,7 +3664,7 @@
+ ;; ??? Look up negscc insn.  See pa.md for example.
+ (define_insn "*neg_scc_insn"
+   [(set (match_operand:SI 0 "dest_reg_operand" "=w")
+-	(neg:SI (match_operator:SI 1 "proper_comparison_operator"
++	(neg:SI (match_operator 1 "proper_comparison_operator"
+ 		 [(reg CC_REG) (const_int 0)])))]
+   ""
+   "mov %0,-1\;sub.%D1 %0,%0,%0"
+@@ -3673,7 +3673,7 @@
+ 
+ (define_insn "*not_scc_insn"
+   [(set (match_operand:SI 0 "dest_reg_operand" "=w")
+-	(not:SI (match_operator:SI 1 "proper_comparison_operator"
++	(not:SI (match_operator 1 "proper_comparison_operator"
+ 		 [(reg CC_REG) (const_int 0)])))]
+   ""
+   "mov %0,1\;sub.%d1 %0,%0,%0"
+diff --git a/gcc/config/arc/predicates.md b/gcc/config/arc/predicates.md
+index a6b81a147897..56e54784a374 100644
+--- a/gcc/config/arc/predicates.md
++++ b/gcc/config/arc/predicates.md
+@@ -415,7 +415,7 @@
+ ;; Return 1 if OP is a comparison operator valid for the mode of CC.
+ ;; This allows the use of MATCH_OPERATOR to recognize all the branch insns.
+ 
+-(define_predicate "proper_comparison_operator"
++(define_special_predicate "proper_comparison_operator"
+   (match_code "eq, ne, le, lt, ge, gt, leu, ltu, geu, gtu, unordered, ordered, uneq, unge, ungt, unle, unlt, ltgt")
+ {
+   enum rtx_code code = GET_CODE (op);
+@@ -466,7 +466,7 @@
+   }
+ })
+ 
+-(define_predicate "equality_comparison_operator"
++(define_special_predicate "equality_comparison_operator"
+   (match_code "eq, ne"))
+ 
+ (define_predicate "brcc_nolimm_operator"
+-- 
+2.7.4
+
diff --git a/toolchain/gcc/patches/6.3.0/0089-ARC-FIX-Attribute-naked-do-not-emit-return-instructi.patch b/toolchain/gcc/patches/6.3.0/0089-ARC-FIX-Attribute-naked-do-not-emit-return-instructi.patch
new file mode 100644
index 0000000..aecc34f
--- /dev/null
+++ b/toolchain/gcc/patches/6.3.0/0089-ARC-FIX-Attribute-naked-do-not-emit-return-instructi.patch
@@ -0,0 +1,64 @@
+From e18f1496a2f405188c3a0ab64bc593a7e0c422ab Mon Sep 17 00:00:00 2001
+From: Claudiu Zissulescu <claziss at synopsys.com>
+Date: Wed, 11 Jan 2017 13:25:35 +0100
+Subject: [PATCH 89/89] [ARC][FIX] Attribute 'naked': do not emit return
+ instructions.
+
+---
+ gcc/config/arc/arc.c                   | 6 +-----
+ gcc/testsuite/gcc.target/arc/naked-1.c | 2 +-
+ gcc/testsuite/gcc.target/arc/naked-2.c | 4 ++--
+ 3 files changed, 4 insertions(+), 8 deletions(-)
+
+diff --git a/gcc/config/arc/arc.c b/gcc/config/arc/arc.c
+index b49c54ffe470..135606708d28 100644
+--- a/gcc/config/arc/arc.c
++++ b/gcc/config/arc/arc.c
+@@ -3135,11 +3135,7 @@ arc_expand_epilogue (int sibcall_p)
+ 
+   /* Naked functions don't have epilogue.  */
+   if (ARC_NAKED_P (fn_type))
+-    {
+-      if (sibcall_p == FALSE)
+-	emit_jump_insn (gen_simple_return ());
+-      return;
+-    }
++    return;
+ 
+   size = arc_compute_frame_size ();
+ 
+diff --git a/gcc/testsuite/gcc.target/arc/naked-1.c b/gcc/testsuite/gcc.target/arc/naked-1.c
+index e8e4f7cd3152..e45f433f73cd 100644
+--- a/gcc/testsuite/gcc.target/arc/naked-1.c
++++ b/gcc/testsuite/gcc.target/arc/naked-1.c
+@@ -10,9 +10,9 @@ foo (int n, int m)
+   bar (n + m);
+ }
+ /* { dg-final { scan-assembler "\tbl @bar" } } */
+-/* { dg-final { scan-assembler "\tj.* \\\[blink\\\]" } } */
+ 
+ /* Look for things that would appear in a non-naked function, but which
+    should not appear in a naked function.  */
++/* { dg-final { scan-assembler-not "\tj.* \\\[blink\\\]" } } */
+ /* { dg-final { scan-assembler-not "\tst.* " } } */
+ /* { dg-final { scan-assembler-not "\tmov fp,sp" } } */
+diff --git a/gcc/testsuite/gcc.target/arc/naked-2.c b/gcc/testsuite/gcc.target/arc/naked-2.c
+index 7ada2cea6390..7b7262f79167 100644
+--- a/gcc/testsuite/gcc.target/arc/naked-2.c
++++ b/gcc/testsuite/gcc.target/arc/naked-2.c
+@@ -17,10 +17,10 @@ foo (int n, int m)
+   bar (n + m);
+ }
+ /* { dg-final { scan-assembler "\tbl @bar" } } */
+-/* { dg-final { scan-assembler "\trtie" { xfail { arc700 || arc6xx } } } } */
+-/* { dg-final { scan-assembler "j.*\[ilink1\]" { xfail { archs || arcem } } } } */
+ 
+ /* Look for things that would appear in a non-naked function, but which
+    should not appear in a naked function.  */
++/* { dg-final { scan-assembler-not "\trtie" } } */
++/* { dg-final { scan-assembler-not "j.*\[ilink1\]" } } */
+ /* { dg-final { scan-assembler-not "\tst.* " } } */
+ /* { dg-final { scan-assembler-not "\tmov fp,sp" } } */
+-- 
+2.7.4
+
-- 
2.10.2




More information about the Lede-dev mailing list