]> git.ipfire.org Git - thirdparty/gcc.git/blobdiff - gcc/config/arc/arc.h
Update copyright years.
[thirdparty/gcc.git] / gcc / config / arc / arc.h
index f5ef48f0f8648aa744f1dfde1c2d3112f05f210d..161056d1529325c8a861de48943bd04ba86789ae 100644 (file)
@@ -1,13 +1,5 @@
 /* Definitions of target machine for GNU compiler, Synopsys DesignWare ARC cpu.
-   Copyright (C) 1994-2014 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@codito.com)
-   Ramana Radhakrishnan(ramana.radhakrishnan@codito.com)
+   Copyright (C) 1994-2020 Free Software Foundation, Inc.
 
 This file is part of GCC.
 
@@ -28,6 +20,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?
@@ -37,6 +31,11 @@ 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)
+
+#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)      \
@@ -50,70 +49,11 @@ 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()      \
- do {                                  \
-    builtin_define ("__arc__");                \
-    if (TARGET_A5)                     \
-      builtin_define ("__A5__");       \
-    else 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__");  \
-      }                                        \
-    if (TARGET_NORM)                   \
-      {                                        \
-       builtin_define ("__ARC_NORM__");\
-       builtin_define ("__Xnorm");     \
-      }                                        \
-    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_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)
-
-#if DEFAULT_LIBC == LIBC_UCLIBC
-
-#define TARGET_OS_CPP_BUILTINS() \
-  do \
-    { \
-      GNU_USER_TARGET_OS_CPP_BUILTINS (); \
-    } \
-  while (0)
-#endif
+#define TARGET_CPU_CPP_BUILTINS() arc_cpu_cpp_builtins (pfile)
 
-/* Match the macros used in the assembler.  */
+/* 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} \
@@ -122,126 +62,64 @@ 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} \
-"
-
-#define CC1_SPEC "\
-%{EB:%{EL:%emay not use both -EB and -EL}} \
-%{EB:-mbig-endian} %{EL:-mlittle-endian} \
-"
+%(subtarget_cpp_spec)"
 
-#define ASM_DEFAULT "-mARC700 -mEA"
-
-#define ASM_SPEC  "\
-%{mbig-endian|EB:-EB} %{EL} \
-%{mcpu=A5|mcpu=a5|mA5:-mA5} \
-%{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*} \
-%{msimd} \
-%{mmac-d16} %{mmac-24} %{mdsp-packa} %{mcrc} %{mdvbf} %{mtelephony} %{mxy} \
-%{mcpu=ARC700|!mcpu=*:%{mlock}} \
-%{mcpu=ARC700|!mcpu=*:%{mswape}} \
-%{mcpu=ARC700|!mcpu=*:%{mrtsc}} \
+#undef CC1_SPEC
+#define CC1_SPEC "%{EB:%{EL:%emay not use both -EB and -EL}}   \
+%{EB:-mbig-endian} %{EL:-mlittle-endian}                       \
+%{G*}                                                          \
 "
+extern const char *arc_cpu_to_as (int argc, const char **argv);
 
-#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*: %{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\
-    %{fopenmp|ftree-parallelize-loops=*:%: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}"
-#endif
+#define EXTRA_SPEC_FUNCTIONS                   \
+  { "cpu_to_as", arc_cpu_to_as },
 
-#if DEFAULT_LIBC != LIBC_UCLIBC
-#define STARTFILE_SPEC "%{!shared:crt0.o%s} crti%O%s %{pg|p:crtg.o%s} 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}"
+/* This macro defines names of additional specifications to put in the specs
+   that can be used in various specifications like CC1_SPEC.  Its definition
+   is an initializer with a subgrouping for each command option.
 
-#endif
+   Each subgrouping contains a string constant, that defines the
+   specification name, and a string constant that used by the GCC driver
+   program.
 
-#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"
+   Do not define this macro if it does not need to do anything.  */
+#define EXTRA_SPECS                                  \
+  { "subtarget_cpp_spec",      SUBTARGET_CPP_SPEC }, \
+  SUBTARGET_EXTRA_SPECS
 
+#ifndef SUBTARGET_EXTRA_SPECS
+#define SUBTARGET_EXTRA_SPECS
 #endif
 
-#if DEFAULT_LIBC == LIBC_UCLIBC
-#undef LIB_SPEC
-#define LIB_SPEC  \
-  "%{pthread:-lpthread} \
-   %{shared:-lc} \
-   %{!shared:%{pg|p|profile:-lgmon -u profil --defsym __profil=profil} -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}"
+#ifndef SUBTARGET_CPP_SPEC
+#define SUBTARGET_CPP_SPEC ""
 #endif
 
+#undef ASM_SPEC
+#define ASM_SPEC  "%{mbig-endian|EB:-EB} %{EL} "                       \
+  "%:cpu_to_as(%{mcpu=*:%*}) %{mspfp*} %{mdpfp*} "                      \
+  "%{mfpu=fpuda*:-mfpuda} %{mcode-density}"
+
+#define OPTION_DEFAULT_SPECS                                           \
+  {"cpu", "%{!mcpu=*:%{!mARC*:%{!marc*:%{!mA7:%{!mA6:-mcpu=%(VALUE)}}}}}" }
+
 #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 \
-  "%{mARC5|mA5: -mcpu=A5 %<mARC5 %<mA5}" \
-  "%{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.  */
 
 #define TARGET_MIXED_CODE (TARGET_MIXED_CODE_SET)
 
 #define TARGET_SPFP (TARGET_SPFP_FAST_SET || TARGET_SPFP_COMPACT_SET)
-#define TARGET_DPFP (TARGET_DPFP_FAST_SET || TARGET_DPFP_COMPACT_SET)
+#define TARGET_DPFP (TARGET_DPFP_FAST_SET || TARGET_DPFP_COMPACT_SET   \
+                    || TARGET_FP_DP_AX)
 
 #define SUBTARGET_SWITCHES
 
@@ -250,12 +128,9 @@ along with GCC; see the file COPYING3.  If not see
 
 /* Non-zero means the cpu supports norm instruction.  This flag is set by
    default for A7, and only for pre A7 cores when -mnorm is given.  */
-#define TARGET_NORM (TARGET_ARC700 || TARGET_NORM_SET)
+#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))
+#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.  */
@@ -267,28 +142,47 @@ along with GCC; see the file COPYING3.  If not see
 /* Should we try to unalign likely taken branches without a delay slot.  */
 #define TARGET_UNALIGN_BRANCH (TARGET_ARC700 && !optimize_size)
 
-/* Should we upsize short delayed branches with a short delay insn?  */
-#define TARGET_UPSIZE_DBR (TARGET_ARC700 && !optimize_size)
-
 /* Should we add padding before a return insn to avoid mispredict?  */
 #define TARGET_PAD_RETURN (TARGET_ARC700 && !optimize_size)
 
 /* For an anulled-true delay slot insn for a delayed branch, should we only
    use conditional execution?  */
-#define TARGET_AT_DBR_CONDEXEC  (!TARGET_ARC700)
-
-#define TARGET_A5 (arc_cpu == PROCESSOR_A5)
-#define TARGET_ARC600 (arc_cpu == PROCESSOR_ARC600)
-#define TARGET_ARC601 (arc_cpu == PROCESSOR_ARC601)
-#define TARGET_ARC700 (arc_cpu == PROCESSOR_ARC700)
+#define TARGET_AT_DBR_CONDEXEC  (!TARGET_ARC700 && !TARGET_V2)
+
+#define TARGET_ARC600 ((arc_selected_cpu->arch_info->arch_id   \
+                       == BASE_ARCH_6xx)                       \
+                      && (TARGET_BARREL_SHIFTER))
+#define TARGET_ARC601 ((arc_selected_cpu->arch_info->arch_id   \
+                       == BASE_ARCH_6xx)                       \
+                      && (!TARGET_BARREL_SHIFTER))
+#define TARGET_ARC700 (arc_selected_cpu->arch_info->arch_id    \
+                      == BASE_ARCH_700)
+/* An NPS400 is a specialisation of ARC700, so it is correct for NPS400
+   TARGET_ARC700 is true, and TARGET_NPS400 is true.  */
+#define TARGET_NPS400 ((arc_selected_cpu->arch_info->arch_id   \
+                       == BASE_ARCH_700)                       \
+                      && (arc_selected_cpu->processor          \
+                          == PROCESSOR_nps400))
+#define TARGET_EM (arc_selected_cpu->arch_info->arch_id == BASE_ARCH_em)
+#define TARGET_HS (arc_selected_cpu->arch_info->arch_id == BASE_ARCH_hs)
+#define TARGET_V2 (TARGET_EM || TARGET_HS)
+
+#ifndef UNALIGNED_ACCESS_DEFAULT
+#define UNALIGNED_ACCESS_DEFAULT 0
+#endif
 
-/* Recast the cpu class to be the cpu attribute.  */
-#define arc_cpu_attr ((enum attr_cpu)arc_cpu)
+#ifndef TARGET_NPS_BITOPS_DEFAULT
+#define TARGET_NPS_BITOPS_DEFAULT 0
+#endif
 
-#ifndef MULTILIB_DEFAULTS
-#define MULTILIB_DEFAULTS { "mARC700" }
+#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
@@ -358,8 +252,8 @@ if (GET_MODE_CLASS (MODE) == MODE_INT               \
    construct.
 */
 
-#define ADJUST_FIELD_ALIGN(FIELD, COMPUTED) \
-(TYPE_MODE (strip_array_types (TREE_TYPE (FIELD))) == DFmode \
+#define ADJUST_FIELD_ALIGN(FIELD, TYPE, COMPUTED) \
+(TYPE_MODE (strip_array_types (TYPE)) == DFmode \
  ? MIN ((COMPUTED), 32) : (COMPUTED))
 
 
@@ -375,13 +269,6 @@ if (GET_MODE_CLASS (MODE) == MODE_INT              \
 /* The best alignment to use in cases where we have a choice.  */
 #define FASTEST_ALIGNMENT 32
 
-/* Make strings word-aligned so strcpy from constants will be faster.  */
-#define CONSTANT_ALIGNMENT(EXP, ALIGN)  \
-  ((TREE_CODE (EXP) == STRING_CST      \
-    && (ALIGN) < FASTEST_ALIGNMENT)    \
-   ? FASTEST_ALIGNMENT : (ALIGN))
-
-
 /* Make arrays of chars word-aligned for the same reasons.  */
 #define LOCAL_ALIGNMENT(TYPE, ALIGN)             \
   (TREE_CODE (TYPE) == ARRAY_TYPE               \
@@ -399,7 +286,7 @@ if (GET_MODE_CLASS (MODE) == MODE_INT               \
 /* On the ARC the lower address bits are masked to 0 as necessary.  The chip
    won't croak when given an unaligned address, but the insn will still fail
    to produce the correct result.  */
-#define STRICT_ALIGNMENT 1
+#define STRICT_ALIGNMENT (!unaligned_access)
 
 /* Layout of source language data types.  */
 
@@ -414,14 +301,17 @@ 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
 
-#define SIZE_TYPE "long unsigned int"
-#define PTRDIFF_TYPE "long int"
-#define WCHAR_TYPE "int"
-#define WCHAR_TYPE_SIZE 32
+#undef SIZE_TYPE
+#define SIZE_TYPE "unsigned int"
+
+#undef PTRDIFF_TYPE
+#define PTRDIFF_TYPE "int"
 
+#undef WCHAR_TYPE
+#define WCHAR_TYPE "int"
 
-/* ashwin : shifted from arc.c:102 */
-#define PROGRAM_COUNTER_REGNO 63
+#undef WCHAR_TYPE_SIZE
+#define WCHAR_TYPE_SIZE 32
 
 /* Standard register usage.  */
 
@@ -436,7 +326,7 @@ if (GET_MODE_CLASS (MODE) == MODE_INT               \
    argument pointer.  */
 
 /* r63 is pc, r64-r127 = simd vregs, r128-r143 = simd dma config regs
-   r144, r145 = lp_start, lp_end
+   r144, r145 = ARG_POINTER, FRAME_POINTER
    and therefore the pseudo registers start from r146. */
 #define FIRST_PSEUDO_REGISTER 146
 
@@ -472,17 +362,16 @@ if (GET_MODE_CLASS (MODE) == MODE_INT             \
 
    By default, the extension registers are not available.  */
 /* Present implementations only have VR0-VR23 only.  */
-/* ??? FIXME: r27 and r31 should not be fixed registers.  */
 #define FIXED_REGISTERS \
 { 0, 0, 0, 0, 0, 0, 0, 0,      \
   0, 0, 0, 0, 0, 0, 0, 0,      \
   0, 0, 0, 0, 0, 0, 0, 0,      \
-  0, 0, 1, 1, 1, 1, 1, 1,      \
+  0, 0, 1, 0, 1, 1, 1, 1,      \
                                \
   1, 1, 1, 1, 1, 1, 1, 1,      \
   0, 0, 0, 0, 1, 1, 1, 1,      \
   1, 1, 1, 1, 1, 1, 1, 1,      \
-  1, 1, 1, 1, 0, 1, 1, 1,       \
+  1, 1, 1, 1, 1, 1, 1, 1,       \
                                \
   0, 0, 0, 0, 0, 0, 0, 0,       \
   0, 0, 0, 0, 0, 0, 0, 0,       \
@@ -509,7 +398,7 @@ if (GET_MODE_CLASS (MODE) == MODE_INT               \
   1, 1, 1, 1, 1, 1, 1, 1,      \
   1, 1, 1, 1, 1, 0, 0, 0,      \
   0, 0, 0, 0, 0, 0, 0, 0,      \
-  0, 0, 1, 1, 1, 1, 1, 1,      \
+  0, 0, 1, 0, 1, 1, 1, 1,      \
                                \
   1, 1, 1, 1, 1, 1, 1, 1,      \
   1, 1, 1, 1, 1, 1, 1, 1,      \
@@ -533,42 +422,34 @@ if (GET_MODE_CLASS (MODE) == MODE_INT             \
 /* If defined, an initializer for a vector of integers, containing the
    numbers of hard registers in the order in which GCC should
    prefer to use them (from most preferred to least).  */
-#define REG_ALLOC_ORDER \
-{ 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 0, 1,                        \
-  16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26,                          \
+#define REG_ALLOC_ORDER                                                        \
+{                                                                      \
+  /* General registers.  */                                            \
+  2, 3, 12, 13, 14, 15, 1, 0, 4, 5, 6, 7, 8, 9, 10, 11,                        \
+  16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 30,                  \
+  /* Extension core registers.  */                                     \
   32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47,      \
-  48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62,          \
-  27, 28, 29, 30, 31, 63}
-
-/* Return number of consecutive hard regs needed starting at reg REGNO
-   to hold something of mode MODE.
-   This is ordinarily the length in words of a value of mode MODE
-   but can be less for certain modes in special long registers.  */
-#define HARD_REGNO_NREGS(REGNO, MODE) \
-((GET_MODE_SIZE (MODE) == 16 \
-  && REGNO >= ARC_FIRST_SIMD_VR_REG && REGNO <= ARC_LAST_SIMD_VR_REG) ? 1 \
- : (GET_MODE_SIZE (MODE) + UNITS_PER_WORD - 1) / UNITS_PER_WORD)
-
-/* Value is 1 if hard register REGNO can hold a value of machine-mode MODE.  */
-extern unsigned int arc_hard_regno_mode_ok[];
-extern unsigned int arc_mode_class[];
-#define HARD_REGNO_MODE_OK(REGNO, MODE) \
-((arc_hard_regno_mode_ok[REGNO] & arc_mode_class[MODE]) != 0)
-
-/* A C expression that is nonzero if it is desirable to choose
-   register allocation so as to avoid move instructions between a
-   value of mode MODE1 and a value of mode MODE2.
-
-   If `HARD_REGNO_MODE_OK (R, MODE1)' and `HARD_REGNO_MODE_OK (R,
-   MODE2)' are ever different for any R, then `MODES_TIEABLE_P (MODE1,
-   MODE2)' must be zero.  */
-
-/* Tie QI/HI/SI modes together.  */
-#define MODES_TIEABLE_P(MODE1, MODE2) \
-(GET_MODE_CLASS (MODE1) == MODE_INT            \
- && GET_MODE_CLASS (MODE2) == MODE_INT         \
- && GET_MODE_SIZE (MODE1) <= UNITS_PER_WORD    \
- && GET_MODE_SIZE (MODE2) <= UNITS_PER_WORD)
+  48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59,                      \
+  /* VR regs.  */                                                      \
+  64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79,      \
+  80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95,      \
+  96, 97, 98, 99, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109,    \
+  110, 111, 112, 113, 114, 115, 116, 117, 118, 119, 120, 121, 122, 123, \
+  124, 125, 126, 127,                                                  \
+  /* DMA registers.  */                                                        \
+  128, 129, 130, 131, 132, 133, 134, 135, 136, 137, 138, 139, 140, 141, \
+  142, 143,                                                            \
+  /* Register not used for general use.  */                            \
+  62, FRAME_POINTER_REGNUM, ARG_POINTER_REGNUM,                                \
+  SP_REG, ILINK1_REG, RETURN_ADDR_REGNUM, LP_COUNT, CC_REG, PCL_REG    \
+}
+
+/* Use different register alloc ordering for Thumb.  */
+#define ADJUST_REG_ALLOC_ORDER arc_adjust_reg_alloc_order ()
+
+/* Tell IRA to use the order we define rather than messing it up with its
+   own cost calculations.  */
+#define HONOR_REG_ALLOC_ORDER 1
 
 /* Internal macros to classify a register number as to whether it's a
    general purpose register for compact insns (r0-r3,r12-r15), or
@@ -609,22 +490,15 @@ enum reg_class
 {
    NO_REGS,
    R0_REGS,                    /* 'x' */
-   GP_REG,                     /* 'Rgp' */
-   FP_REG,                     /* 'f' */
-   SP_REGS,                    /* 'b' */
-   LPCOUNT_REG,                /* 'l' */
-   LINK_REGS,                  /* 'k' */
-   DOUBLE_REGS,                        /* D0, D1 */
-   SIMD_VR_REGS,               /* VR00-VR63 */
-   SIMD_DMA_CONFIG_REGS,       /* DI0-DI7,DO0-DO7 */
+   R0R1_CD_REGS,               /* 'Rsd' */
+   R0R3_CD_REGS,               /* 'Rcd' */
    ARCOMPACT16_REGS,           /* 'q' */
-   AC16_BASE_REGS,             /* 'e' */
    SIBCALL_REGS,               /* "Rsc" */
+   AC16_H_REGS,                        /* 'h' */
+   DOUBLE_REGS,                        /* 'D' */
    GENERAL_REGS,               /* 'r' */
-   MPY_WRITABLE_CORE_REGS,     /* 'W' */
-   WRITABLE_CORE_REGS,         /* 'w' */
-   CHEAP_CORE_REGS,            /* 'c' */
-   ALL_CORE_REGS,              /* 'Rac' */
+   SIMD_VR_REGS,               /* 'v' */
+   SIMD_DMA_CONFIG_REGS,       /* 'd' */
    ALL_REGS,
    LIM_REG_CLASSES
 };
@@ -633,26 +507,19 @@ enum reg_class
 
 /* Give names of register classes as strings for dump file.   */
 #define REG_CLASS_NAMES          \
-{                         \
-  "NO_REGS",                     \
-  "R0_REGS",                     \
-  "GP_REG",                      \
-  "FP_REG",                      \
-  "SP_REGS",             \
-  "LPCOUNT_REG",         \
-  "LINK_REGS",                   \
-  "DOUBLE_REGS",          \
-  "SIMD_VR_REGS",         \
-  "SIMD_DMA_CONFIG_REGS", \
-  "ARCOMPACT16_REGS",            \
-  "AC16_BASE_REGS",       \
+{                        \
+  "NO_REGS",             \
+  "R0_REGS",             \
+  "R0R1_CD_REGS",        \
+  "R0R3_CD_REGS",        \
+  "ARCOMPACT16_REGS",    \
   "SIBCALL_REGS",        \
-  "GENERAL_REGS",                \
-  "MPY_WRITABLE_CORE_REGS",   \
-  "WRITABLE_CORE_REGS",   \
-  "CHEAP_CORE_REGS",     \
-  "ALL_CORE_REGS",       \
-  "ALL_REGS"             \
+  "AC16_H_REGS",         \
+  "DOUBLE_REGS",         \
+  "GENERAL_REGS",        \
+  "SIMD_VR_REGS",        \
+  "SIMD_DMA_CONFIG_REGS", \
+  "ALL_REGS"             \
 }
 
 /* Define which registers fit in which classes.
@@ -660,30 +527,19 @@ enum reg_class
    of length N_REG_CLASSES.  */
 
 #define REG_CLASS_CONTENTS \
-{                                                                                                      \
-  {0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000},             /* No Registers */                 \
-  {0x00000001, 0x00000000, 0x00000000, 0x00000000, 0x00000000},      /* 'x', r0 register , r0 */       \
-  {0x04000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000},      /* 'Rgp', Global Pointer, r26 */  \
-  {0x08000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000},      /* 'f', Frame Pointer, r27 */     \
-  {0x10000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000},      /* 'b', Stack Pointer, r28 */     \
-  {0x00000000, 0x10000000, 0x00000000, 0x00000000, 0x00000000},      /* 'l', LPCOUNT Register, r60 */  \
-  {0xe0000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000},      /* 'k', LINK Registers, r29-r31 */        \
-  {0x00000000, 0x00000f00, 0x00000000, 0x00000000, 0x00000000},      /* 'D', D1, D2 Registers */       \
-  {0x00000000, 0x00000000, 0xffffffff, 0xffffffff, 0x00000000},      /* 'V', VR00-VR63 Registers */    \
-  {0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x0000ffff},      /* 'V', DI0-7,DO0-7 Registers */  \
-  {0x0000f00f, 0x00000000, 0x00000000, 0x00000000, 0x00000000},             /* 'q', r0-r3, r12-r15 */          \
-  {0x1000f00f, 0x00000000, 0x00000000, 0x00000000, 0x00000000},             /* 'e', r0-r3, r12-r15, sp */      \
-  {0x1c001fff, 0x00000000, 0x00000000, 0x00000000, 0x00000000},    /* "Rsc", r0-r12 */ \
-  {0x9fffffff, 0xc0000000, 0x00000000, 0x00000000, 0x00000000},      /* 'r', r0-r28, blink, ap and pcl */      \
-  {0xffffffff, 0x00000000, 0x00000000, 0x00000000, 0x00000000},      /* 'W',  r0-r31 */ \
-  /* Include ap / pcl in WRITABLE_CORE_REGS for sake of symmetry.  As these \
-     registers are fixed, it does not affect the literal meaning of the \
-     constraints, but it makes it a superset of GENERAL_REGS, thus \
-     enabling some operations that would otherwise not be possible.  */ \
-  {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 */ \
-  {0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0x0003ffff}       /* All Registers */               \
+{                                                                      \
+  {0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000}, /* NO_REGS.  */\
+  {0x00000001, 0x00000000, 0x00000000, 0x00000000, 0x00000000}, /* 'x'.  */ \
+  {0x00000003, 0x00000000, 0x00000000, 0x00000000, 0x00000000}, /* 'Rsd'.  */ \
+  {0x0000000f, 0x00000000, 0x00000000, 0x00000000, 0x00000000}, /* 'Rcd'.  */ \
+  {0x0000f00f, 0x00000000, 0x00000000, 0x00000000, 0x00000000}, /* 'q'.  */ \
+  {0x00001fff, 0x00000000, 0x00000000, 0x00000000, 0x00000000}, /* 'Rsc'.  */ \
+  {0x9fffffff, 0x00000000, 0x00000000, 0x00000000, 0x00000000}, /* 'h'.  */ \
+  {0x00000000, 0x00000f00, 0x00000000, 0x00000000, 0x00000000}, /* 'D'.  */ \
+  {0xffffffff, 0x8fffffff, 0x00000000, 0x00000000, 0x00030000}, /* 'r'.  */ \
+  {0x00000000, 0x00000000, 0xffffffff, 0xffffffff, 0x00000000}, /* 'v'.  */ \
+  {0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x0000ffff}, /* 'd'.  */ \
+  {0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0x0003ffff} /* ALL_REGS.  */\
 }
 
 /* Local macros to mark the first and last regs of different classes.  */
@@ -695,6 +551,12 @@ enum reg_class
 #define ARC_FIRST_SIMD_DMA_CONFIG_OUT_REG  136
 #define ARC_LAST_SIMD_DMA_CONFIG_REG       143
 
+/* ARCv2 double-register accumulator.  */
+#define ACC_REG_FIRST 58
+#define ACC_REG_LAST  59
+#define ACCL_REGNO    (TARGET_BIG_ENDIAN ? ACC_REG_FIRST + 1 : ACC_REG_FIRST)
+#define ACCH_REGNO    (TARGET_BIG_ENDIAN ? ACC_REG_FIRST : ACC_REG_FIRST + 1)
+
 /* The same information, inverted:
    Return the class number of the smallest class containing
    reg number REGNO.  This could be a conditional expression
@@ -714,16 +576,22 @@ extern enum reg_class arc_regno_reg_class[];
 /* The class value for valid base registers. A base register is one used in
    an address which is the register value plus a displacement.  */
 
-#define BASE_REG_CLASS (TARGET_MIXED_CODE ? AC16_BASE_REGS : GENERAL_REGS)
+#define BASE_REG_CLASS GENERAL_REGS
 
 /* These assume that REGNO is a hard or pseudo reg number.
    They give nonzero only if REGNO is a hard reg of the suitable 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) == FRAME_POINTER_REGNUM)                                        \
+   || ((REGNO) == PCL_REG)                                             \
+   || ((unsigned) reg_renumber[REGNO] < 29)                            \
+   || ((unsigned) (REGNO) == (unsigned) arc_tp_regno)                  \
+   || (fixed_regs[REGNO] == 0 && IN_RANGE (REGNO, 32, 59))             \
+   || (fixed_regs[REGNO] == 0 && (REGNO) == R30_REG))
 
 #define REGNO_OK_FOR_INDEX_P(REGNO) REGNO_OK_FOR_BASE_P(REGNO)
 
@@ -749,6 +617,7 @@ extern enum reg_class arc_regno_reg_class[];
   ((unsigned) (((X) >> (SHIFT)) + 0x100) \
    < 0x200 - ((unsigned) (OFFSET) >> (SHIFT)))
 #define SIGNED_INT12(X) ((unsigned) ((X) + 0x800) < 0x1000)
+#define SIGNED_INT16(X) ((unsigned) ((X) + 0x8000) < 0x10000)
 #define LARGE_INT(X) \
 (((X) < 0) \
  ? (X) >= (-(HOST_WIDE_INT) 0x7fffffff - 1) \
@@ -758,6 +627,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)
 
@@ -765,7 +636,7 @@ extern enum reg_class arc_regno_reg_class[];
 
 /* Define this macro if pushing a word onto the stack moves the stack
    pointer to a smaller address.  */
-#define STACK_GROWS_DOWNWARD
+#define STACK_GROWS_DOWNWARD 1
 
 /* Define this if the nominal address of the stack frame
    is at the high-address end of the local variables;
@@ -773,12 +644,6 @@ extern enum reg_class arc_regno_reg_class[];
    goes at a more negative offset in the frame.  */
 #define FRAME_GROWS_DOWNWARD 1
 
-/* Offset within stack frame to start allocating local variables at.
-   If FRAME_GROWS_DOWNWARD, this is the offset to the END of the
-   first local allocated.  Otherwise, it is the offset to the BEGINNING
-   of the first local allocated.  */
-#define STARTING_FRAME_OFFSET 0
-
 /* Offset from the stack pointer register to the first location at which
    outgoing arguments are placed.  */
 #define STACK_POINTER_OFFSET (0)
@@ -812,11 +677,12 @@ arc_return_addr_rtx(COUNT,FRAME)
 #define STACK_POINTER_REGNUM 28
 
 /* Base register for access to local variables of the function.  */
-#define FRAME_POINTER_REGNUM 27
+#define FRAME_POINTER_REGNUM 145
+#define HARD_FRAME_POINTER_REGNUM 27
 
 /* Base register for access to arguments of the function. This register
    will be eliminated into either fp or sp.  */
-#define ARG_POINTER_REGNUM 62
+#define ARG_POINTER_REGNUM 144
 
 #define RETURN_ADDR_REGNUM 31
 
@@ -845,10 +711,10 @@ arc_return_addr_rtx(COUNT,FRAME)
    for a call to a function whose data type is FNTYPE.
    For a library call, FNTYPE is 0.  */
 #define INIT_CUMULATIVE_ARGS(CUM,FNTYPE,LIBNAME,INDIRECT,N_NAMED_ARGS) \
-((CUM) = 0)
+  ((CUM) = 0)
 
 /* The number of registers used for parameter passing.  Local to this file.  */
-#define MAX_ARC_PARM_REGS 8
+#define MAX_ARC_PARM_REGS (TARGET_RF16 ? 4 : 8)
 
 /* 1 if N is a possible register number for function argument passing.  */
 #define FUNCTION_ARG_REGNO_P(N) \
@@ -901,10 +767,6 @@ arc_return_addr_rtx(COUNT,FRAME)
 /* Tell GCC to use RETURN_IN_MEMORY.  */
 #define DEFAULT_PCC_STRUCT_RETURN 0
 
-/* Register in which address to store a structure value
-   is passed to a function, or 0 to use `invisible' first argument.  */
-#define STRUCT_VALUE 0
-
 /* EXIT_IGNORE_STACK should be nonzero if, when returning from a function,
    the stack pointer does not matter.  The value is tested only in
    functions that have frame pointers.
@@ -913,6 +775,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
@@ -928,8 +792,9 @@ arc_return_addr_rtx(COUNT,FRAME)
 
 #define ELIMINABLE_REGS                                        \
 {{ARG_POINTER_REGNUM, STACK_POINTER_REGNUM},           \
- {ARG_POINTER_REGNUM, FRAME_POINTER_REGNUM},           \
- {FRAME_POINTER_REGNUM, STACK_POINTER_REGNUM}}
+ {ARG_POINTER_REGNUM, HARD_FRAME_POINTER_REGNUM},      \
+ {FRAME_POINTER_REGNUM, STACK_POINTER_REGNUM}, \
+ {FRAME_POINTER_REGNUM, HARD_FRAME_POINTER_REGNUM}}
 
 /* Define the offset between two registers, one to be eliminated, and the other
    its replacement, at the start of a routine.  */
@@ -937,20 +802,16 @@ extern int arc_initial_elimination_offset(int from, int to);
 #define INITIAL_ELIMINATION_OFFSET(FROM, TO, OFFSET)                    \
   (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"))
+/* All the work done in PROFILE_HOOK, but still required.  */
+#undef FUNCTION_PROFILER
+#define FUNCTION_PROFILER(STREAM, LABELNO) do { } while (0)
 
 #define NO_PROFILE_COUNTERS  1
 
 /* Trampolines.  */
 
 /* Length in units of the trampoline for entering a nested function.  */
-#define TRAMPOLINE_SIZE 20
+#define TRAMPOLINE_SIZE 16
 
 /* Alignment required for a trampoline in bits .  */
 /* For actual data alignment we just need 32, no more than the stack;
@@ -979,13 +840,14 @@ extern int arc_initial_elimination_offset(int from, int to);
    a special predicate for the memory operand of stores, like for the SH.  */
 
 /* Recognize any constant value that is a valid address.  */
-#define CONSTANT_ADDRESS_P(X) \
-(flag_pic?arc_legitimate_pic_addr_p (X): \
-(GET_CODE (X) == LABEL_REF || GET_CODE (X) == SYMBOL_REF       \
- || GET_CODE (X) == CONST_INT || GET_CODE (X) == CONST))
+#define CONSTANT_ADDRESS_P(X)                                  \
+  (flag_pic ? (arc_legitimate_pic_addr_p (X) || LABEL_P (X)):  \
+   (GET_CODE (X) == LABEL_REF || GET_CODE (X) == SYMBOL_REF    \
   || GET_CODE (X) == CONST_INT || GET_CODE (X) == CONST))
 
 /* 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.
@@ -1001,18 +863,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))
@@ -1057,7 +916,7 @@ extern int arc_initial_elimination_offset(int from, int to);
 
 /* Given a comparison code (EQ, NE, etc.) and the first operand of a COMPARE,
    return the mode to be used for the comparison.  */
-/*extern enum machine_mode arc_select_cc_mode ();*/
+/*extern machine_mode arc_select_cc_mode ();*/
 #define SELECT_CC_MODE(OP, X, Y) \
 arc_select_cc_mode (OP, X, Y)
 
@@ -1067,17 +926,6 @@ arc_select_cc_mode (OP, X, Y)
 
 /* Costs.  */
 
-/* Compute extra cost of moving data between one register class
-   and another.  */
-#define REGISTER_MOVE_COST(MODE, CLASS, TO_CLASS) \
-   arc_register_move_cost ((MODE), (CLASS), (TO_CLASS))
-
-/* Compute the cost of moving data between registers and memory.  */
-/* Memory is 3 times as expensive as registers.
-   ??? Is that the right way to look at it?  */
-#define MEMORY_MOVE_COST(MODE,CLASS,IN) \
-(GET_MODE_SIZE (MODE) <= UNITS_PER_WORD ? 6 : 12)
-
 /* The cost of a branch insn.  */
 /* ??? What's the right value here?  Branches are certainly more
    expensive than reg->reg moves.  */
@@ -1108,7 +956,7 @@ arc_select_cc_mode (OP, X, Y)
 /* Define this macro if it is as good or better to call a constant
    function address than to call an address kept in a register.  */
 /* On the ARC, calling through registers is slow.  */
-#define NO_FUNCTION_CSE
+#define NO_FUNCTION_CSE 1
 
 /* Section selection.  */
 /* WARNING: These section names also appear in dwarfout.c.  */
@@ -1163,7 +1011,8 @@ arc_select_cc_mode (OP, X, Y)
    check it either.  You need not define this macro if all constants
    (including SYMBOL_REF) can be immediate operands when generating
    position independent code.  */
-#define LEGITIMATE_PIC_OPERAND_P(X)  (arc_legitimate_pic_operand_p(X))
+#define LEGITIMATE_PIC_OPERAND_P(X)  \
+  (!arc_raw_symbolic_reference_mentioned_p ((X), true))
 
 /* PIC and small data don't mix on ARC because they use the same register.  */
 #define SDATA_BASE_REGNUM 26
@@ -1183,10 +1032,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.  */
@@ -1314,6 +1165,7 @@ do {                                                      \
 #endif
 #define SET_ASM_OP "\t.set\t"
 
+extern char rname29[], rname30[];
 extern char rname56[], rname57[], rname58[], rname59[];
 /* How to refer to registers in assembler output.
    This sequence is indexed by compiler's hard-register-number (see above).  */
@@ -1321,11 +1173,11 @@ extern char rname56[], rname57[], rname58[], rname59[];
 {  "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",   "gp",   "fp",       "sp", "ilink1", "ilink2", "blink",      \
+  "r24",  "r25",   "gp",   "fp",       "sp",  rname29,  rname30, "blink",      \
   "r32",  "r33",  "r34",  "r35",      "r36",    "r37",    "r38",   "r39",      \
    "d1",   "d1",   "d2",   "d2",      "r44",    "r45",    "r46",   "r47",      \
   "r48",  "r49",  "r50",  "r51",      "r52",    "r53",    "r54",   "r55",      \
-  rname56,rname57,rname58,rname59,"lp_count",    "cc",     "ap",   "pcl",      \
+  rname56,rname57,rname58,rname59,"lp_count",    "cc",   "limm",   "pcl",      \
   "vr0",  "vr1",  "vr2",  "vr3",      "vr4",    "vr5",    "vr6",   "vr7",       \
   "vr8",  "vr9", "vr10", "vr11",     "vr12",   "vr13",   "vr14",  "vr15",      \
  "vr16", "vr17", "vr18", "vr19",     "vr20",   "vr21",   "vr22",  "vr23",      \
@@ -1336,7 +1188,22 @@ extern char rname56[], rname57[], rname58[], rname59[];
  "vr56", "vr57", "vr58", "vr59",     "vr60",   "vr61",   "vr62",  "vr63",      \
   "dr0",  "dr1",  "dr2",  "dr3",      "dr4",    "dr5",    "dr6",   "dr7",      \
   "dr0",  "dr1",  "dr2",  "dr3",      "dr4",    "dr5",    "dr6",   "dr7",      \
-  "lp_start", "lp_end" \
+  "arg", "frame" \
+}
+
+#define ADDITIONAL_REGISTER_NAMES              \
+{                                              \
+  {"ilink",  29},                              \
+  {"r29",    29},                              \
+  {"r30",    30},                              \
+  {"r40",    40},                              \
+  {"r41",    41},                              \
+  {"r42",    42},                              \
+  {"r43",    43},                              \
+  {"r56",    56},                              \
+  {"r57",    57},                              \
+  {"r58",    58},                              \
+  {"r59",    59}                               \
 }
 
 /* Entry to the insn conditionalizer.  */
@@ -1373,29 +1240,45 @@ do {                                                    \
   ASM_GENERATE_INTERNAL_LABEL (label, "L", VALUE);     \
   fprintf (FILE, "\t.word ");                          \
   assemble_name (FILE, label);                         \
-  fprintf(FILE, "\n");                                 \
+  fprintf (FILE, "\n");                                        \
 } while (0)
 
 /* This is how to output an element of a case-vector that is relative.  */
-#define ASM_OUTPUT_ADDR_DIFF_ELT(FILE, BODY, VALUE, REL) \
-do {                                                   \
-  char label[30];                                      \
-  ASM_GENERATE_INTERNAL_LABEL (label, "L", VALUE);     \
-  switch (GET_MODE (BODY))                             \
-    {                                                  \
-    case QImode: fprintf (FILE, "\t.byte "); break;    \
-    case HImode: fprintf (FILE, "\t.hword "); break;   \
-    case SImode: fprintf (FILE, "\t.word "); break;    \
-    default: gcc_unreachable ();                       \
-    }                                                  \
-  assemble_name (FILE, label);                         \
-  fprintf (FILE, "-");                                 \
-  ASM_GENERATE_INTERNAL_LABEL (label, "L", REL);       \
-  assemble_name (FILE, label);                         \
-  if (TARGET_COMPACT_CASESI)                           \
-    fprintf (FILE, " + %d", 4 + arc_get_unalign ());   \
-  fprintf(FILE, "\n");                                  \
-} while (0)
+#define ASM_OUTPUT_ADDR_DIFF_ELT(FILE, BODY, VALUE, REL)       \
+  do {                                                         \
+    char label[30];                                            \
+    ASM_GENERATE_INTERNAL_LABEL (label, "L", VALUE);           \
+    if (!TARGET_BI_BIH)                                                \
+      {                                                                \
+       switch (GET_MODE (BODY))                                \
+         {                                                     \
+         case E_QImode: fprintf (FILE, "\t.byte "); break;     \
+         case E_HImode: fprintf (FILE, "\t.hword "); break;    \
+         case E_SImode: fprintf (FILE, "\t.word "); break;     \
+         default: gcc_unreachable ();                          \
+         }                                                     \
+       assemble_name (FILE, label);                            \
+       fprintf (FILE, "-");                                    \
+       ASM_GENERATE_INTERNAL_LABEL (label, "L", REL);          \
+       assemble_name (FILE, label);                            \
+       fprintf (FILE, "\n");                                   \
+      }                                                                \
+    else                                                       \
+      {                                                                \
+      switch (GET_MODE (BODY))                                 \
+       {                                                       \
+       case E_SImode: fprintf (FILE, "\tb\t@"); break;         \
+       case E_HImode:                                          \
+       case E_QImode: fprintf (FILE, "\tb_s\t@"); break;       \
+       default: gcc_unreachable ();                            \
+       }                                                       \
+      assemble_name (FILE, label);                             \
+      fprintf(FILE, "\n");                                     \
+    }                                                          \
+  } while (0)
+
+/* Defined to also emit an .align in elfos.h.  We don't want that.  */
+#undef ASM_OUTPUT_CASE_LABEL
 
 /* ADDR_DIFF_VECs are in the text section and thus can affect the
    current alignment.  */
@@ -1403,7 +1286,8 @@ do {                                                      \
   do                                                    \
     {                                                   \
       if (GET_CODE (PATTERN (JUMPTABLE)) == ADDR_DIFF_VEC \
-         && ((GET_MODE_SIZE (GET_MODE (PATTERN (JUMPTABLE))) \
+         && ((GET_MODE_SIZE (as_a <scalar_int_mode>    \
+                             (GET_MODE (PATTERN (JUMPTABLE)))) \
               * XVECLEN (PATTERN (JUMPTABLE), 1) + 1)  \
              & 2))                                     \
       arc_toggle_unalign ();                           \
@@ -1420,7 +1304,7 @@ do {                                                      \
    of a loop.  */
 /* On the ARC, align loops to 4 byte boundaries unless doing all-out size
    optimization.  */
-#define LOOP_ALIGN JUMP_ALIGN
+#define LOOP_ALIGN(X) 0
 
 #define LABEL_ALIGN(LABEL) (arc_label_align (LABEL))
 
@@ -1440,10 +1324,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[4];
-
 /* Debugging information.  */
 
 /* Generate DBX and DWARF debugging information.  */
@@ -1481,17 +1361,9 @@ 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_DATA_REGNO(N)        \
-  ((N) < 4 ? (N) : INVALID_REGNUM)
+#define EH_RETURN_STACKADJ_RTX   gen_rtx_REG (Pmode, 2)
 
 /* Turn off splitting of long stabs.  */
 #define DBX_CONTIN_LENGTH 0
@@ -1502,45 +1374,44 @@ extern int arc_return_address_regs[4];
    for the index in the tablejump instruction.
    If we have pc relative case vectors, we start the case vector shortening
    with QImode.  */
-#define CASE_VECTOR_MODE \
-  ((optimize && (CASE_VECTOR_PC_RELATIVE || flag_pic)) ? QImode : Pmode)
+#define CASE_VECTOR_MODE                                               \
+  (TARGET_BI_BIH ? SImode                                              \
+   : (optimize && (CASE_VECTOR_PC_RELATIVE || flag_pic)) ? QImode : Pmode)
 
 /* Define as C expression which evaluates to nonzero if the tablejump
    instruction expects the table to contain offsets from the address of the
    table.
    Do not define this if the table should contain absolute addresses.  */
-#define CASE_VECTOR_PC_RELATIVE TARGET_CASE_VECTOR_PC_RELATIVE
-
-#define CASE_VECTOR_SHORTEN_MODE(MIN_OFFSET, MAX_OFFSET, BODY) \
-  CASE_VECTOR_SHORTEN_MODE_1 \
-    (MIN_OFFSET, TARGET_COMPACT_CASESI ? MAX_OFFSET + 6 : MAX_OFFSET, BODY)
-
-#define CASE_VECTOR_SHORTEN_MODE_1(MIN_OFFSET, MAX_OFFSET, BODY) \
-((MIN_OFFSET) >= 0 && (MAX_OFFSET) <= 255 \
- ? (ADDR_DIFF_VEC_FLAGS (BODY).offset_unsigned = 1, QImode) \
- : (MIN_OFFSET) >= -128 && (MAX_OFFSET) <= 127 \
- ? (ADDR_DIFF_VEC_FLAGS (BODY).offset_unsigned = 0, QImode) \
- : (MIN_OFFSET) >= 0 && (MAX_OFFSET) <= 65535 \
- ? (ADDR_DIFF_VEC_FLAGS (BODY).offset_unsigned = 1, HImode) \
- : (MIN_OFFSET) >= -32768 && (MAX_OFFSET) <= 32767 \
- ? (ADDR_DIFF_VEC_FLAGS (BODY).offset_unsigned = 0, HImode) \
- : SImode)
-
-#define ADDR_VEC_ALIGN(VEC_INSN) \
-  (exact_log2 (GET_MODE_SIZE (GET_MODE (PATTERN (VEC_INSN)))))
-#undef ASM_OUTPUT_BEFORE_CASE_LABEL
-#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 CASE_VECTOR_PC_RELATIVE                                        \
+  (TARGET_CASE_VECTOR_PC_RELATIVE || TARGET_BI_BIH)
+
+#define CASE_VECTOR_SHORTEN_MODE(MIN_OFFSET, MAX_OFFSET, BODY)         \
+  (TARGET_BI_BIH ?                                             \
+   ((MIN_OFFSET) >= -512 && (MAX_OFFSET) <= 508 ? HImode : SImode)     \
+   : ((MIN_OFFSET) >= 0 && (MAX_OFFSET) <= 255                         \
+      ? (ADDR_DIFF_VEC_FLAGS (BODY).offset_unsigned = 1, QImode)       \
+      : (MIN_OFFSET) >= -128 && (MAX_OFFSET) <= 127                    \
+      ? (ADDR_DIFF_VEC_FLAGS (BODY).offset_unsigned = 0, QImode)       \
+      : (MIN_OFFSET) >= 0 && (MAX_OFFSET) <= 65535                     \
+      ? (ADDR_DIFF_VEC_FLAGS (BODY).offset_unsigned = 1, HImode)       \
+      : (MIN_OFFSET) >= -32768 && (MAX_OFFSET) <= 32767                        \
+      ? (ADDR_DIFF_VEC_FLAGS (BODY).offset_unsigned = 0, HImode)       \
+      : SImode))
+
+#define ADDR_VEC_ALIGN(VEC_INSN)                                       \
+  (TARGET_BI_BIH ? 0                                                   \
+   : exact_log2 (GET_MODE_SIZE (as_a <scalar_int_mode>                 \
+                               (GET_MODE (PATTERN (VEC_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
    on the full register even if a narrower mode is specified.  */
-#define WORD_REGISTER_OPERATIONS
+#define WORD_REGISTER_OPERATIONS 1
 
 /* Define if loading in MODE, an integral mode narrower than BITS_PER_WORD
    will either zero-extend or sign-extend.  The value of this macro should
@@ -1553,26 +1424,13 @@ extern int arc_return_address_regs[4];
    in one reasonably fast instruction.  */
 #define MOVE_MAX 4
 
-/* Let the movmem expander handle small block moves.  */
-#define MOVE_BY_PIECES_P(LEN, ALIGN)  0
-#define CAN_MOVE_BY_PIECES(SIZE, ALIGN) \
-  (move_by_pieces_ninsns (SIZE, ALIGN, MOVE_MAX_PIECES + 1) \
-   < (unsigned int) MOVE_RATIO (!optimize_size))
-
-/* Undo the effects of the movmem pattern presence on STORE_BY_PIECES_P .  */
+/* Undo the effects of the cpymem 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
-
-/* Value is 1 if truncating an integer of INPREC bits to OUTPREC bits
-   is done just by pretending it is already truncated.  */
-#define TRULY_NOOP_TRUNCATION(OUTPREC, INPREC) 1
+#define SHIFT_COUNT_TRUNCATED 1
 
 /* We assume that the store-condition-codes instructions store 0 for false
    and some other value for true.  This is the value stored for true.  */
@@ -1594,25 +1452,47 @@ 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    = 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)
 
-/* 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 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)
+
+/* 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.  */
 #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.  */
@@ -1638,7 +1518,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))
 
 #define CALL_ATTR(X, NAME) \
   ((CALL_P (X) || NONJUMP_INSN_P (X)) \
@@ -1646,38 +1527,34 @@ extern enum arc_function_type arc_compute_function_type (struct function *);
    && GET_CODE (PATTERN (X)) != CLOBBER \
    && get_attr_is_##NAME (X) == IS_##NAME##_YES) \
 
-#define REVERSE_CONDITION(CODE,MODE) \
-       (((MODE) == CC_FP_GTmode || (MODE) == CC_FP_GEmode \
-         || (MODE) == CC_FP_UNEQmode || (MODE) == CC_FP_ORDmode \
-         || (MODE) == CC_FPXmode) \
-        ? reverse_condition_maybe_unordered ((CODE)) \
-        : reverse_condition ((CODE)))
+#define REVERSE_CONDITION(CODE,MODE)                            \
+  (((MODE) == CC_FP_GTmode || (MODE) == CC_FP_GEmode            \
+    || (MODE) == CC_FP_UNEQmode || (MODE) == CC_FP_ORDmode      \
+    || (MODE) == CC_FPXmode || (MODE) == CC_FPU_UNEQmode        \
+    || (MODE) == CC_FPUmode || (MODE) == CC_FPUEmode)           \
+   ? reverse_condition_maybe_unordered ((CODE))                         \
+   : reverse_condition ((CODE)))
 
 #define ADJUST_INSN_LENGTH(X, LENGTH) \
   ((LENGTH) \
    = (GET_CODE (PATTERN (X)) == SEQUENCE \
       ? ((LENGTH) \
-        + arc_adjust_insn_length (as_a <rtx_sequence *> (PATTERN (X))->insn (0), \
-                                  get_attr_length (XVECEXP (PATTERN (X), \
-                                                   0, 0)), \
-                                  true) \
-        - get_attr_length (XVECEXP (PATTERN (X), 0, 0)) \
-        + arc_adjust_insn_length (as_a <rtx_sequence *> (PATTERN (X))->insn (1), \
-                                  get_attr_length (XVECEXP (PATTERN (X), \
-                                                   0, 1)), \
-                                  true) \
-        - get_attr_length (XVECEXP (PATTERN (X), 0, 1))) \
+        + arc_adjust_insn_length ( \
+             as_a <rtx_sequence *> (PATTERN (X))->insn (0), \
+            get_attr_length (as_a <rtx_sequence *> (PATTERN (X))->insn (0)), \
+            true)                                                      \
+        - get_attr_length (as_a <rtx_sequence *> (PATTERN (X))->insn (0)) \
+        + arc_adjust_insn_length ( \
+            as_a <rtx_sequence *> (PATTERN (X))->insn (1), \
+            get_attr_length (as_a <rtx_sequence *> (PATTERN (X))->insn (1)), \
+            true)                                                      \
+        - get_attr_length (as_a <rtx_sequence *> (PATTERN (X))->insn (1))) \
       : arc_adjust_insn_length ((X), (LENGTH), false)))
 
 #define IS_ASM_LOGICAL_LINE_SEPARATOR(C,STR) ((C) == '`')
 
 #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
@@ -1693,4 +1570,68 @@ enum
 #define SFUNC_CHECK_PREDICABLE \
   (GET_CODE (PATTERN (insn)) != COND_EXEC || !flag_pic || !TARGET_MEDIUM_CALLS)
 
+/* MPYW feature macro.  Only valid for ARCHS and ARCEM cores.  */
+#define TARGET_MPYW     ((arc_mpy_option > 0) && TARGET_V2)
+/* Full ARCv2 multiplication feature macro.  */
+#define TARGET_MULTI    ((arc_mpy_option > 1) && TARGET_V2)
+/* General MPY feature macro.  */
+#define TARGET_MPY      ((TARGET_ARC700 && (!TARGET_NOMPY_SET)) || TARGET_MULTI)
+/* ARC700 MPY feature macro.  */
+#define TARGET_ARC700_MPY (TARGET_ARC700 && (!TARGET_NOMPY_SET))
+/* 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)
+/* 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.  */
+#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.  */
+#define TARGET_FP_DP_BASE   ((arc_fpu_build & FPU_DP) != 0)
+/* Single precision floating point support with fused operation.  */
+#define TARGET_FP_SP_FUSED  ((arc_fpu_build & FPU_SF) != 0)
+/* Double precision floating point support with fused operation.  */
+#define TARGET_FP_DP_FUSED  ((arc_fpu_build & FPU_DF) != 0)
+/* Single precision floating point conversion instruction support.  */
+#define TARGET_FP_SP_CONV   ((arc_fpu_build & FPU_SC) != 0)
+/* Double precision floating point conversion instruction support.  */
+#define TARGET_FP_DP_CONV   ((arc_fpu_build & FPU_DC) != 0)
+/* Single precision floating point SQRT/DIV instruction support.  */
+#define TARGET_FP_SP_SQRT   ((arc_fpu_build & FPU_SD) != 0)
+/* Double precision floating point SQRT/DIV instruction support.  */
+#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))
+/* DBNZ support is available for ARCv2 core3 and newer cpus.  */
+#define TARGET_DBNZ (TARGET_V2 && (arc_tune >= ARC_TUNE_CORE_3))
+
+/* BI/BIH feature macro.  */
+#define TARGET_BI_BIH (TARGET_BRANCH_INDEX && TARGET_CODE_DENSITY)
+
+/* The default option for BI/BIH instructions.  */
+#define DEFAULT_BRANCH_INDEX 0
+
+#ifndef TARGET_LRA
+#define TARGET_LRA arc_lra_p()
+#endif
+
 #endif /* GCC_ARC_H */