[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]%&\", ®);
+ 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