From dbdbd982df2d044f3b43b2f41ef1ada5667160f9 Mon Sep 17 00:00:00 2001
From: Nick Clifton <nickc@gcc.gnu.org>
Date: Thu, 31 Jan 2013 18:36:02 +0000
Subject: [PATCH] lib1funcs.S: Add support for e3v5 architecture variant.

	* config/v850/lib1funcs.S: Add support for e3v5 architecture
	variant.

	* config/v850/constraints.md (Q): Define as a memory constraint.
	* config/v850/predicates.md (label_ref_operand): New predicate.
	(e3v5_shift_operand): New predicate.
	(ior_operator): New predicate.
	* config/v850/t-v850: Add e3v5 multilib.
	* config/v850/v850-protos.h (v850_adjust_insn_length): Prototype.
	(v850_gen_movdi): Prototype.
	* config/v850/v850.c: Add support for e3v5 architecture.
	Rename all uses of TARGET_V850E || TARGET_V850E2_ALL to
	TARGET_V850E_UP.
	(construct_save_jarl): Add e3v5 long JARL support.
	(v850_adjust_insn_length): New function.  Adjust length of call
	insns when using e3v5 instructions.
	(v850_gen_movdi): New function: Generate instructions to move a
	DImode value.
	* config/v850/v850.h (TARGET_CPU_v850e3v5): Define.
	(CPP_SPEC): Define __v850e3v5__ as appropriate.
	(TARGET_USE_FPU): Enable for e3v5.
	(CONST_OK_FOR_W): New macro.
	(ADJUST_INSN_LENGTH): Define.
	* config/v850/v850.md (UNSPEC_LOOP): Define.
	(attr cpu): Add v850e3v5.
	Rename all uses of TARGET_V850E2 to TARGET_V850E2V3_UP.
	(movdi): New pattern.
	(movdi_internal): New pattern.
	(cbranchsf4): Conditionalize on TARGET_USE_FPU.
	(cbranchdf4): Conditionalize on TARGET_USE_FPU.
	(cstoresf4): Likewise.
	(cstoredf4): Likewise.
	(insv): New pattern.
	(rotlso3_a): New pattern.
	(rotlsi3_b): New pattern
	(rotlsi3_v850e3v5): New pattern.
	(doloop_begin): New pattern.
	(fix_loop_counter): New pattern.
	(doloop_end): New pattern.
	(branch_normal): Add e3v5 long branch support.
	(branch_invert): Likewise.
	(branch_z_normal): Likewise.
	(branch_z_invert): Likewise.
	(branch_nz_normal): Likewise.
	(branch_nz_invert): Likewise.
	(call_internal_short): Add e3v5 register-indirect JARL support.
	(call_internal_long): Likewise.
	(call_value_internal_short): Likewise.
	(call_value_internal_long): Likewise.
	* config/v850/v850.opt (mv850e3v5, mv850e2v4): New options.
	(mloop): New option.
	* config.gcc: Add support for configuring v840e3v5 target.
	* doc/invoke.texi: Document new v850 specific command line
	options.

From-SVN: r195623
---
 gcc/ChangeLog                  |  55 ++++
 gcc/config.gcc                 |   7 +-
 gcc/config/v850/constraints.md |   2 +-
 gcc/config/v850/predicates.md  |  20 ++
 gcc/config/v850/t-v850         |   3 +
 gcc/config/v850/v850-protos.h  |   2 +
 gcc/config/v850/v850.c         |  86 ++++++-
 gcc/config/v850/v850.h         |  38 ++-
 gcc/config/v850/v850.md        | 445 +++++++++++++++++++++++++--------
 gcc/config/v850/v850.opt       |  11 +
 gcc/doc/invoke.texi            | 170 +++++++++++--
 libgcc/ChangeLog               |   7 +-
 libgcc/config/v850/lib1funcs.S |   6 +-
 13 files changed, 698 insertions(+), 154 deletions(-)

diff --git a/gcc/ChangeLog b/gcc/ChangeLog
index b3c1c52de798..341e9aa434bb 100644
--- a/gcc/ChangeLog
+++ b/gcc/ChangeLog
@@ -1,3 +1,58 @@
+2013-01-31  Hiroyuki Ono  <hiroyuki.ono.jc@renesas.com>
+	    Nick Clifton  <nickc@redhat.com>
+
+	* config/v850/constraints.md (Q): Define as a memory constraint.
+	* config/v850/predicates.md (label_ref_operand): New predicate.
+	(e3v5_shift_operand): New predicate.
+	(ior_operator): New predicate.
+	* config/v850/t-v850: Add e3v5 multilib.
+	* config/v850/v850-protos.h (v850_adjust_insn_length): Prototype.
+	(v850_gen_movdi): Prototype.
+	* config/v850/v850.c: Add support for e3v5 architecture.
+	Rename all uses of TARGET_V850E || TARGET_V850E2_ALL to
+	TARGET_V850E_UP.
+	(construct_save_jarl): Add e3v5 long JARL support.
+	(v850_adjust_insn_length): New function.  Adjust length of call
+	insns when using e3v5 instructions.
+	(v850_gen_movdi): New function: Generate instructions to move a
+	DImode value.
+	* config/v850/v850.h (TARGET_CPU_v850e3v5): Define.
+	(CPP_SPEC): Define __v850e3v5__ as appropriate.
+	(TARGET_USE_FPU): Enable for e3v5.
+	(CONST_OK_FOR_W): New macro.
+	(ADJUST_INSN_LENGTH): Define.
+	* config/v850/v850.md (UNSPEC_LOOP): Define.
+	(attr cpu): Add v850e3v5.
+	Rename all uses of TARGET_V850E2 to TARGET_V850E2V3_UP.
+	(movdi): New pattern.
+	(movdi_internal): New pattern.
+	(cbranchsf4): Conditionalize on TARGET_USE_FPU.
+	(cbranchdf4): Conditionalize on TARGET_USE_FPU.
+	(cstoresf4): Likewise.
+	(cstoredf4): Likewise.
+	(insv): New pattern.
+	(rotlso3_a): New pattern.
+	(rotlsi3_b): New pattern
+	(rotlsi3_v850e3v5): New pattern.
+	(doloop_begin): New pattern.
+	(fix_loop_counter): New pattern.
+	(doloop_end): New pattern.
+	(branch_normal): Add e3v5 long branch support.
+	(branch_invert): Likewise.
+	(branch_z_normal): Likewise.
+	(branch_z_invert): Likewise.
+	(branch_nz_normal): Likewise.
+	(branch_nz_invert): Likewise.
+	(call_internal_short): Add e3v5 register-indirect JARL support.
+	(call_internal_long): Likewise.
+	(call_value_internal_short): Likewise.
+	(call_value_internal_long): Likewise.
+	* config/v850/v850.opt (mv850e3v5, mv850e2v4): New options.
+	(mloop): New option.
+	* config.gcc: Add support for configuring v840e3v5 target.
+	* doc/invoke.texi: Document new v850 specific command line
+	options.
+
 2013-01-31  Paul Koning  <ni1d@arrl.net>
 
 	PR debug/55059
diff --git a/gcc/config.gcc b/gcc/config.gcc
index ca76fc8539d8..b6a6ad0636de 100644
--- a/gcc/config.gcc
+++ b/gcc/config.gcc
@@ -2554,6 +2554,9 @@ v850-*-rtems*)
 	;;
 v850*-*-*)
 	case ${target} in
+	v850e3v5-*-*)
+		target_cpu_default="TARGET_CPU_v850e3v5"
+		;;
 	v850e2v3-*-*)
 		target_cpu_default="TARGET_CPU_v850e2v3"
 		;;
@@ -3614,7 +3617,7 @@ case "${target}" in
 	v850*-*-*)
 		supported_defaults=cpu
 		case ${with_cpu} in
-		"" | v850e | v850e1 | v850e2 | v850es | v850e2v3)
+		"" | v850e | v850e1 | v850e2 | v850es | v850e2v3 | v850e3v5)
 			# OK
 			;;
 		*)
@@ -3741,7 +3744,7 @@ case ${target} in
 		case "x$with_cpu" in
 		x)
 			;;
-		xv850e | xv850e1 | xv850e2 | xv850e2v3)
+		xv850e | xv850e1 | xv850e2 | xv850e2v3 | xv850e3v5)
 			target_cpu_default2="TARGET_CPU_$with_cpu"
 			;;
 		xv850es)
diff --git a/gcc/config/v850/constraints.md b/gcc/config/v850/constraints.md
index a10122da0e4d..11a97c9da2c1 100644
--- a/gcc/config/v850/constraints.md
+++ b/gcc/config/v850/constraints.md
@@ -76,7 +76,7 @@
        (match_test "0")))
 
 ;;; Extra constraints.
-(define_constraint "Q"
+(define_memory_constraint "Q"
   "A memory address that does not contain a symbol address."
   (and (match_code "mem")
        (match_test "ep_memory_operand (op, mode, FALSE)")))
diff --git a/gcc/config/v850/predicates.md b/gcc/config/v850/predicates.md
index 37851c46a89a..10674a9d6332 100644
--- a/gcc/config/v850/predicates.md
+++ b/gcc/config/v850/predicates.md
@@ -498,6 +498,26 @@
   return op == CONST0_RTX(mode);
 })
 
+(define_predicate "label_ref_operand"
+  (match_code "label_ref")
+)
+
+
+(define_predicate "e3v5_shift_operand"
+  (match_code "const_int,reg")
+  {
+    if (CONST_INT_P (op))
+      return IN_RANGE (INTVAL (op), 0, 31);
+    return true;
+  }
+)
+
+(define_predicate "ior_operator"
+  (match_code "ior")
+{
+  return (GET_CODE (op) == IOR);
+})
+
 ;; Return true if the floating point comparison operation
 ;; given produces a canonical answer.
 (define_predicate "v850_float_z_comparison_operator"
diff --git a/gcc/config/v850/t-v850 b/gcc/config/v850/t-v850
index f87631602449..b91b5057d7d5 100644
--- a/gcc/config/v850/t-v850
+++ b/gcc/config/v850/t-v850
@@ -20,6 +20,9 @@
 MULTILIB_OPTIONS  = m8byte-align mgcc-abi msoft-float
 MULTILIB_DIRNAMES =  8byte        gcc-abi  soft-float
 
+MULTILIB_OPTIONS  += mv850e3v5
+MULTILIB_DIRNAMES +=  v850e3v5
+
 TCFLAGS = -mno-app-regs -msmall-sld -Wa,-mwarn-signed-overflow -Wa,-mwarn-unsigned-overflow
 
 v850-c.o: $(srcdir)/config/v850/v850-c.c $(CONFIG_H) $(SYSTEM_H) coretypes.h \
diff --git a/gcc/config/v850/v850-protos.h b/gcc/config/v850/v850-protos.h
index 151f5b598817..be253dd5dbf7 100644
--- a/gcc/config/v850/v850-protos.h
+++ b/gcc/config/v850/v850-protos.h
@@ -39,6 +39,8 @@ extern char * construct_restore_jr          (rtx);
 extern char * construct_dispose_instruction (rtx);
 extern char * construct_prepare_instruction (rtx);
 extern int    ep_memory_operand             (rtx, enum machine_mode, int);
+extern int    v850_adjust_insn_length       (rtx, int);
+extern const char * v850_gen_movdi          (rtx *);
 extern rtx    v850_gen_compare              (enum rtx_code, enum machine_mode,
 					     rtx, rtx);
 extern enum machine_mode  v850_gen_float_compare (enum rtx_code,
diff --git a/gcc/config/v850/v850.c b/gcc/config/v850/v850.c
index 12c7928f5aef..67cc2c267164 100644
--- a/gcc/config/v850/v850.c
+++ b/gcc/config/v850/v850.c
@@ -824,7 +824,7 @@ output_move_single (rtx * operands)
 	    return "movhi hi0(%1),%.,%0";
 
 	  /* A random constant.  */
-	  else if (TARGET_V850E || TARGET_V850E2_ALL)
+	  else if (TARGET_V850E_UP)
 	      return "mov %1,%0";
 	  else
 	    return "movhi hi(%1),%.,%0\n\tmovea lo(%1),%0,%0";
@@ -846,7 +846,7 @@ output_move_single (rtx * operands)
 	    return "movhi hi0(%F1),%.,%0";
 
 	  /* A random constant.  */
-	else if (TARGET_V850E || TARGET_V850E2_ALL)
+	else if (TARGET_V850E_UP)
 	      return "mov %F1,%0";
 
 	  else
@@ -863,7 +863,7 @@ output_move_single (rtx * operands)
 	       || GET_CODE (src) == SYMBOL_REF
 	       || GET_CODE (src) == CONST)
 	{
-	  if (TARGET_V850E || TARGET_V850E2_ALL) 
+	  if (TARGET_V850E_UP) 
 	    return "mov hilo(%1),%0";
 	  else
 	    return "movhi hi(%1),%.,%0\n\tmovea lo(%1),%0,%0";
@@ -1018,7 +1018,7 @@ ep_memory_offset (enum machine_mode mode, int unsignedp ATTRIBUTE_UNUSED)
     case QImode:
       if (TARGET_SMALL_SLD)
 	max_offset = (1 << 4);
-      else if ((TARGET_V850E || TARGET_V850E2_ALL)
+      else if ((TARGET_V850E_UP)
 		&& unsignedp)
 	max_offset = (1 << 4);
       else
@@ -1028,7 +1028,7 @@ ep_memory_offset (enum machine_mode mode, int unsignedp ATTRIBUTE_UNUSED)
     case HImode:
       if (TARGET_SMALL_SLD)
 	max_offset = (1 << 5);
-      else if ((TARGET_V850E || TARGET_V850E2_ALL)
+      else if ((TARGET_V850E_UP)
 		&& unsignedp)
 	max_offset = (1 << 5);
       else
@@ -1656,7 +1656,7 @@ expand_prologue (void)
   /* Save/setup global registers for interrupt functions right now.  */
   if (interrupt_handler)
     {
-      if (! TARGET_DISABLE_CALLT && (TARGET_V850E || TARGET_V850E2_ALL))
+      if (! TARGET_DISABLE_CALLT && (TARGET_V850E_UP))
 	emit_insn (gen_callt_save_interrupt ());
       else
 	emit_insn (gen_save_interrupt ());
@@ -1759,7 +1759,7 @@ expand_prologue (void)
       /* Special case interrupt functions that save all registers for a call.  */
       if (interrupt_handler && ((1L << LINK_POINTER_REGNUM) & reg_saved) != 0)
 	{
-	  if (! TARGET_DISABLE_CALLT && (TARGET_V850E || TARGET_V850E2_ALL))
+	  if (! TARGET_DISABLE_CALLT && (TARGET_V850E_UP))
 	    emit_insn (gen_callt_save_all_interrupt ());
 	  else
 	    emit_insn (gen_save_all_interrupt ());
@@ -1967,7 +1967,7 @@ expand_epilogue (void)
       /* And return or use reti for interrupt handlers.  */
       if (interrupt_handler)
         {
-          if (! TARGET_DISABLE_CALLT && (TARGET_V850E || TARGET_V850E2_ALL))
+          if (! TARGET_DISABLE_CALLT && (TARGET_V850E_UP))
             emit_insn (gen_callt_return_interrupt ());
           else
             emit_jump_insn (gen_return_interrupt ());
@@ -2437,8 +2437,11 @@ construct_save_jarl (rtx op)
       else
 	sprintf (name, "__save_%s_%s", reg_names [first], reg_names [last]);
       
-      sprintf (buff, "movhi hi(%s), r0, r11\n\tmovea lo(%s), r11, r11\n\tjarl .+4, r10\n\tadd 4, r10\n\tjmp r11",
-	       name, name);
+      if (TARGET_V850E3V5_UP)
+	sprintf (buff, "mov hilo(%s), r11\n\tjarl [r11], r10", name);
+      else
+	sprintf (buff, "movhi hi(%s), r0, r11\n\tmovea lo(%s), r11, r11\n\tjarl .+4, r10\n\tadd 4, r10\n\tjmp r11",
+		 name, name);
     }
   else
     {
@@ -3048,7 +3051,7 @@ v850_trampoline_init (rtx m_tramp, tree fndecl, rtx chain_value)
 static int
 v850_issue_rate (void)
 {
-  return (TARGET_V850E2_ALL? 2 : 1);
+  return (TARGET_V850E2_UP ? 2 : 1);
 }
 
 /* Implement TARGET_LEGITIMATE_CONSTANT_P.  */
@@ -3082,6 +3085,32 @@ v850_memory_move_cost (enum machine_mode mode,
       return (GET_MODE_SIZE (mode) / 2) * (in ? 3 : 1);
     }
 }
+
+int
+v850_adjust_insn_length (rtx insn, int length)
+{
+  if (TARGET_V850E3V5_UP)
+    {
+      if (CALL_P (insn))
+	{
+	  if (TARGET_LONG_CALLS)
+	    {
+	      /* call_internal_long, call_value_internal_long.  */
+	      if (length == 8)
+		length = 4;
+	      if (length == 16)
+		length = 10;
+	    }
+	  else
+	    {
+	      /* call_internal_short, call_value_internal_short.  */
+	      if (length == 8)
+		length = 4;
+	    }
+	}
+    }
+  return length;
+}
 
 /* V850 specific attributes.  */
 
@@ -3102,7 +3131,6 @@ static const struct attribute_spec v850_attribute_table[] =
   { NULL,                0, 0, false, false, false, NULL, false }
 };
 
-
 static void
 v850_option_override (void)
 {
@@ -3114,6 +3142,40 @@ v850_option_override (void)
     target_flags |= MASK_DISABLE_CALLT;
 }
 
+const char *
+v850_gen_movdi (rtx * operands)
+{
+  if (REG_P (operands[0]))
+    {
+      if (REG_P (operands[1]))
+	{
+	  if (REGNO (operands[0]) == (REGNO (operands[1]) - 1))
+	    return "mov %1, %0; mov %R1, %R0";
+
+	  return "mov %R1, %R0; mov %1, %0";
+	}
+
+      if (MEM_P (operands[1]))
+	{
+	  if (REGNO (operands[0]) & 1)
+	    /* Use two load word instructions to synthesise a load double.  */
+	    return "ld.w %1, %0 ; ld.w %R1, %R0" ;
+
+	  return "ld.dw %1, %0";
+	}
+
+      return "mov %1, %0; mov %R1, %R0";
+    }
+
+  gcc_assert (REG_P (operands[1]));
+
+  if (REGNO (operands[1]) & 1)
+    /* Use two store word instructions to synthesise a store double.  */
+    return "st.w %1, %0 ; st.w %R1, %R0 ";
+  
+  return "st.dw %1, %0";
+}
+
 /* Initialize the GCC target structure.  */
 
 #undef  TARGET_OPTION_OVERRIDE
diff --git a/gcc/config/v850/v850.h b/gcc/config/v850/v850.h
index 573b149e94ed..e08c6220eacb 100644
--- a/gcc/config/v850/v850.h
+++ b/gcc/config/v850/v850.h
@@ -37,7 +37,7 @@ extern GTY(()) rtx v850_compare_op1;
 #define TARGET_CPU_v850e1	3
 #define TARGET_CPU_v850e2	4
 #define TARGET_CPU_v850e2v3	5
-
+#define TARGET_CPU_v850e3v5	6
 
 #ifndef TARGET_CPU_DEFAULT
 #define TARGET_CPU_DEFAULT	TARGET_CPU_generic
@@ -86,7 +86,22 @@ extern GTY(()) rtx v850_compare_op1;
 #define SUBTARGET_CPP_SPEC	"%{!mv*:-D__v850e2v3__} %{mv850e2v3:-D__v850e2v3__}"
 #endif
 
-#define TARGET_V850E2_ALL      (TARGET_V850E2 || TARGET_V850E2V3) 
+#if TARGET_CPU_DEFAULT == TARGET_CPU_v850e3v5
+#undef  MASK_DEFAULT
+#define MASK_DEFAULT            MASK_V850E3V5
+#undef  SUBTARGET_ASM_SPEC
+#define SUBTARGET_ASM_SPEC	"%{!mv*:-mv850e3v5}"
+#undef  SUBTARGET_CPP_SPEC
+#define SUBTARGET_CPP_SPEC	"%{!mv*:-D__v850e3v5__} %{mv850e3v5:-D__v850e3v5__}"
+#undef  TARGET_VERSION
+#define TARGET_VERSION		fprintf (stderr, " (Renesas V850E3V5)");
+#endif
+
+#define TARGET_V850E3V5_UP ((TARGET_V850E3V5))     
+#define TARGET_V850E2V3_UP ((TARGET_V850E2V3) || TARGET_V850E3V5_UP)
+#define TARGET_V850E2_UP   ((TARGET_V850E2)   || TARGET_V850E2V3_UP)
+#define TARGET_V850E_UP    ((TARGET_V850E)    || TARGET_V850E2_UP)
+#define TARGET_ALL         ((TARGET_V850)     || TARGET_V850E_UP)
 
 #define ASM_SPEC "%{m850es:-mv850e1}%{!mv850es:%{mv*:-mv%*}} \
 %{mrelax:-mrelax} \
@@ -96,14 +111,15 @@ extern GTY(()) rtx v850_compare_op1;
 #define LINK_SPEC "%{mgcc-abi:-m v850}"
 
 #define CPP_SPEC "\
+  %{mv850e3v5:-D__v850e3v5__} \
   %{mv850e2v3:-D__v850e2v3__} \
   %{mv850e2:-D__v850e2__} \
   %{mv850es:-D__v850e1__} \
   %{mv850e1:-D__v850e1__} \
   %{mv850e:-D__v850e__} \
   %{mv850:-D__v850__} \
-  %(subtarget_cpp_spec)" \
-  " %{mep:-D__EP__}"
+  %(subtarget_cpp_spec) \
+  %{mep:-D__EP__}"
 
 #define EXTRA_SPECS \
  { "subtarget_asm_spec", SUBTARGET_ASM_SPEC }, \
@@ -111,7 +127,7 @@ extern GTY(()) rtx v850_compare_op1;
 
 
 /* Macro to decide when FPU instructions can be used.  */
-#define TARGET_USE_FPU  (TARGET_V850E2V3 && ! TARGET_SOFT_FLOAT)
+#define TARGET_USE_FPU  (TARGET_V850E2V3_UP && ! TARGET_SOFT_FLOAT)
 
 #define TARGET_CPU_CPP_BUILTINS()		\
   do						\
@@ -136,7 +152,7 @@ extern GTY(()) rtx v850_compare_op1;
     }						\
   while(0)
 
-#define MASK_CPU (MASK_V850 | MASK_V850E | MASK_V850E1 | MASK_V850E2 | MASK_V850E2V3)
+#define MASK_CPU (MASK_V850 | MASK_V850E | MASK_V850E1 | MASK_V850E2 | MASK_V850E2V3 | MASK_V850E3V5)
 
 /* Target machine storage layout */
 
@@ -380,7 +396,8 @@ enum reg_class
   insn_const_int_ok_for_constraint (VALUE, CONSTRAINT_N)
 #define CONST_OK_FOR_O(VALUE) \
   insn_const_int_ok_for_constraint (VALUE, CONSTRAINT_O)
-
+#define CONST_OK_FOR_W(VALUE) \
+  insn_const_int_ok_for_constraint (VALUE, CONSTRAINT_W)
 
 /* Stack layout; function entry, exit and calling.  */
 
@@ -797,9 +814,9 @@ typedef enum
 #define ASM_OUTPUT_ADDR_DIFF_ELT(FILE, BODY, VALUE, REL) 		\
   fprintf (FILE, "\t%s %s.L%d-.L%d%s\n",				\
 	   (TARGET_BIG_SWITCH ? ".long" : ".short"),			\
-	   (0 && ! TARGET_BIG_SWITCH && (TARGET_V850E || TARGET_V850E2_ALL) ? "(" : ""),             \
+	   (0 && ! TARGET_BIG_SWITCH && (TARGET_V850E_UP) ? "(" : ""),             \
 	   VALUE, REL,							\
-	   (0 && ! TARGET_BIG_SWITCH && (TARGET_V850E || TARGET_V850E2_ALL) ? ")>>1" : ""))
+	   (0 && ! TARGET_BIG_SWITCH && (TARGET_V850E_UP) ? ")>>1" : ""))
 
 #define ASM_OUTPUT_ALIGN(FILE, LOG)	\
   if ((LOG) != 0)			\
@@ -960,4 +977,7 @@ extern tree GHS_current_section_names [(int) COUNT_OF_GHS_SECTION_KINDS];
    -isystem <path-to-build-dir>.  */
 #define NO_IMPLICIT_EXTERN_C
 
+#define ADJUST_INSN_LENGTH(INSN, LENGTH) \
+  ((LENGTH) = v850_adjust_insn_length ((INSN), (LENGTH)))
+
 #endif /* ! GCC_V850_H */
diff --git a/gcc/config/v850/v850.md b/gcc/config/v850/v850.md
index f05f2f945c6b..4ed0e40b05fb 100644
--- a/gcc/config/v850/v850.md
+++ b/gcc/config/v850/v850.md
@@ -43,6 +43,7 @@
    (LP_REGNUM       		31)         ; Return address register
    (CC_REGNUM       		32)         ; Condition code pseudo register
    (FCC_REGNUM      		33)         ; Floating Condition code pseudo register
+   (UNSPEC_LOOP                200)         ; loop counter
   ]
 )
 
@@ -59,7 +60,7 @@
 (define_attr "type" "load,store,bit1,mult,macc,div,fpu,single,other"
   (const_string "other"))
 
-(define_attr "cpu" "none,v850,v850e,v850e1,v850e2,v850e2v3"
+(define_attr "cpu" "none,v850,v850e,v850e1,v850e2,v850e2v3,v850e3v5"
   (cond [(match_test "TARGET_V850")
 	 (const_string "v850")
 	 (match_test "TARGET_V850E")
@@ -68,8 +69,10 @@
 	 (const_string "v850e1")
 	 (match_test "TARGET_V850E2")
 	 (const_string "v850e2")
-	 (match_test "TARGET_V850E2")
-	 (const_string "v850e2v3")]
+	 (match_test "TARGET_V850E2V3")
+	 (const_string "v850e2v3")
+	 (match_test "TARGET_V850E3V5")
+	 (const_string "v850e3v5")]	 
 	 (const_string "none")))
 
 ;; Condition code settings.
@@ -109,7 +112,7 @@
 	(sign_extend:SI
 	(mem:QI (plus:SI (match_operand:SI 1 "register_operand" "r")
 			 (match_operand 2 "disp23_operand" "W")))))]
-  "TARGET_V850E2V3"
+  "TARGET_V850E2V3_UP"
   "ld.b %2[%1],%0"
   [(set_attr "length" "4")
    (set_attr "cc" "none_0hit")])
@@ -119,7 +122,7 @@
 	(zero_extend:SI
 	(mem:QI (plus:SI (match_operand:SI 1 "register_operand" "r")
 			 (match_operand 2 "disp23_operand" "W")))))]
-  "TARGET_V850E2V3"
+  "TARGET_V850E2V3_UP"
   "ld.bu %2[%1],%0"
   [(set_attr "length" "4")
    (set_attr "cc" "none_0hit")])
@@ -129,7 +132,7 @@
 	(sign_extend:SI
 	(mem:HI (plus:SI (match_operand:SI 1 "register_operand" "r")
 			 (match_operand 2 "disp23_operand" "W")))))]
-  "TARGET_V850E2V3"
+  "TARGET_V850E2V3_UP"
   "ld.h %2[%1],%0"
   [(set_attr "length" "4")
    (set_attr "cc" "none_0hit")])
@@ -139,7 +142,7 @@
 	(zero_extend:SI
 	(mem:HI (plus:SI (match_operand:SI 1 "register_operand" "r")
 			 (match_operand 2 "disp23_operand" "W")))))]
-  "TARGET_V850E2V3"
+  "TARGET_V850E2V3_UP"
   "ld.hu %2[%1],%0"
   [(set_attr "length" "4")
    (set_attr "cc" "none_0hit")])
@@ -148,7 +151,7 @@
   [(set (match_operand:SI 0 "register_operand" "=r")
 	(mem:SI (plus:SI (match_operand:SI 1 "register_operand" "r")
 			 (match_operand 2 "disp23_operand" "W"))))]
-  "TARGET_V850E2V3"
+  "TARGET_V850E2V3_UP"
   "ld.w %2[%1],%0"
   [(set_attr "length" "4")
    (set_attr "cc" "none_0hit")])
@@ -157,7 +160,7 @@
   [(set (mem:QI (plus:SI (match_operand:SI 0 "register_operand" "r")
 			 (match_operand 1 "disp23_operand" "W")))
 	(match_operand:QI 2 "register_operand" "r"))]
-  "TARGET_V850E2V3"
+  "TARGET_V850E2V3_UP"
   "st.b %2,%1[%0]"
   [(set_attr "length" "4")
    (set_attr "cc" "none_0hit")])
@@ -166,7 +169,7 @@
   [(set (mem:HI (plus:SI (match_operand:SI 0 "register_operand" "r")
 			 (match_operand 1 "disp23_operand" "W")))
 	(match_operand:HI 2 "register_operand" "r"))]
-  "TARGET_V850E2V3"
+  "TARGET_V850E2V3_UP"
   "st.h %2,%1[%0]"
   [(set_attr "length" "4")
    (set_attr "cc" "none_0hit")])
@@ -175,11 +178,47 @@
   [(set (mem:SI (plus:SI (match_operand:SI 0 "register_operand" "r")
 			 (match_operand 1 "disp23_operand" "W")))
 	(match_operand:SI 2 "register_operand" "r"))]
-  "TARGET_V850E2V3"
+  "TARGET_V850E2V3_UP"
   "st.w %2,%1[%0]"
   [(set_attr "length" "4")
    (set_attr "cc" "none_0hit")])
 
+;; movdi
+
+(define_expand "movdi"
+  [(set (match_operand:DI 0 "general_operand")
+	(match_operand:DI 1 "general_operand"))]
+  "TARGET_V850E3V5_UP"
+  {
+    /* One of the ops has to be in a register or 0.  */
+    if (!register_operand (operand0, DImode)
+        && !register_operand (operand1, DImode))
+      operands[1] = copy_to_mode_reg (DImode, operand1);
+
+    if (register_operand (operand0, DImode)
+	&& (CONST_INT_P (operands[1]) || CONST_DOUBLE_P (operands[1])))
+      {
+        int i;
+
+        for (i = 0; i < UNITS_PER_WORD * 2; i += UNITS_PER_WORD)
+          emit_move_insn (simplify_gen_subreg (SImode, operands[0], DImode, i),
+                          simplify_gen_subreg (SImode, operands[1], DImode, i));
+        DONE;
+      }
+  }
+)
+
+(define_insn "*movdi_internal"
+  [(set (match_operand:DI 0 "nonimmediate_operand" "=r,e!r,m")
+	(match_operand:DI 1 "nonimmediate_operand"  "r,m,e!r"))]
+  "TARGET_V850E3V5_UP
+   || (register_operand (operands[0], DImode) && register_operand (operands[1], DImode))"
+  { return v850_gen_movdi (operands); }
+  [(set_attr "length" "4,12,12")
+   (set_attr "cc" "none_0hit")
+   (set_attr "type" "other,load,store")]
+)
+
 ;; movqi
 
 (define_expand "movqi"
@@ -265,7 +304,7 @@
        must be done with HIGH & LO_SUM patterns.  */
     if (CONSTANT_P (operands[1])	
 	&& GET_CODE (operands[1]) != HIGH
-	&& ! (TARGET_V850E || TARGET_V850E2_ALL)
+	&& ! (TARGET_V850E_UP)
 	&& !special_symbolref_operand (operands[1], VOIDmode)
 	&& !(GET_CODE (operands[1]) == CONST_INT
 	     && (CONST_OK_FOR_J (INTVAL (operands[1]))
@@ -297,7 +336,7 @@
 (define_insn "*movsi_internal_v850e"
   [(set (match_operand:SI 0 "general_operand" "=r,r,r,r,Q,r,r,m,m,r")
 	(match_operand:SI 1 "general_operand" "Jr,K,L,Q,Ir,m,R,r,I,i"))]
-  "(TARGET_V850E || TARGET_V850E2_ALL)
+  "(TARGET_V850E_UP)
    && (register_operand (operands[0], SImode)
        || reg_or_0_operand (operands[1], SImode))"
 {
@@ -412,17 +451,17 @@
                      (label_ref (match_operand 3 ""))
                      (pc)))
   (clobber (cc0))]
-  "TARGET_V850E2V3"
+  "TARGET_USE_FPU"
 {
-  v850_compare_op0 = operands[1];
-  v850_compare_op1 = operands[2];
-
-  enum rtx_code cond = GET_CODE(operands[0]);
+  enum rtx_code cond = GET_CODE (operands[0]);
   enum machine_mode mode;
   rtx fcc_reg;
   rtx cc_reg;
   rtx tmp;
 
+  v850_compare_op0 = operands[1];
+  v850_compare_op1 = operands[2];
+
   if (GET_MODE_CLASS (GET_MODE (v850_compare_op0)) != MODE_FLOAT)
     FAIL;
 
@@ -442,7 +481,7 @@
         (match_operator:SI  1 "ordered_comparison_operator"
          [(match_operand:SF 2 "register_operand" "r")
           (match_operand:SF 3 "register_operand" "r")]))]
-  "TARGET_V850E2V3"
+  "TARGET_USE_FPU"
 {
   if (GET_CODE (operands[1]) == GT || GET_CODE (operands[1]) == GE)
     return "cmpf.s %c1, %z2, %z3 ; trfsr ; setf nz, %0";
@@ -466,17 +505,17 @@
                      (label_ref (match_operand 3 ""))
                      (pc)))
   (clobber (cc0))]
-  "TARGET_V850E2V3"
+  "TARGET_USE_FPU"
 {
-  v850_compare_op0 = operands[1];
-  v850_compare_op1 = operands[2];
-
-  enum rtx_code cond = GET_CODE(operands[0]);
+  enum rtx_code cond = GET_CODE (operands[0]);
   enum machine_mode mode;
   rtx fcc_reg;
   rtx cc_reg;
   rtx tmp;
 
+    v850_compare_op0 = operands[1];
+    v850_compare_op1 = operands[2];
+
   if (GET_MODE_CLASS (GET_MODE (v850_compare_op0)) != MODE_FLOAT)
     FAIL;
 
@@ -496,7 +535,7 @@
         (match_operator:SI  1 "ordered_comparison_operator"
          [(match_operand:DF 2 "even_reg_operand"  "r")
           (match_operand:DF 3 "even_reg_operand" "r")]))]
-  "TARGET_V850E2V3"
+  "TARGET_USE_FPU"
 {
   if (GET_CODE (operands[1]) == GT || GET_CODE (operands[1]) == GE)
     return "cmpf.d %c1, %z2, %z3 ; trfsr ; setf nz, %0";
@@ -633,7 +672,7 @@
   [(set (match_operand:SI 0 "register_operand" "=r")
 	(mult:SI (match_operand:SI 1 "register_operand" "%0")
 		 (match_operand:SI 2 "reg_or_int9_operand" "rO")))]
-  "(TARGET_V850E || TARGET_V850E2_ALL)"
+  "(TARGET_V850E_UP)"
   "mul %2,%1,%."
   [(set_attr "length" "4")
    (set_attr "cc" "none_0hit")
@@ -657,9 +696,9 @@
 	(mod:SI (match_dup 1)
 		(match_dup 2)))
    (clobber (reg:CC CC_REGNUM))]
-  "TARGET_V850E || TARGET_V850E2_ALL"
+  "TARGET_V850E_UP"
 {
-  if (TARGET_V850E2_ALL)
+  if (TARGET_V850E2_UP)
     return "divq %2,%0,%3";
    else
     return "div %2,%0,%3";
@@ -676,9 +715,9 @@
 	(umod:SI (match_dup 1)
 		 (match_dup 2)))
    (clobber (reg:CC CC_REGNUM))]
-  "TARGET_V850E || TARGET_V850E2_ALL"
+  "TARGET_V850E_UP"
 {
-  if (TARGET_V850E2_ALL)
+  if (TARGET_V850E2_UP)
     return "divqu %2,%0,%3";
   else
     return "divu %2,%0,%3";
@@ -698,7 +737,7 @@
 	(mod:HI (match_dup 1)
 		(match_dup 2)))
    (clobber (reg:CC CC_REGNUM))]
-  "TARGET_V850E || TARGET_V850E2_ALL"
+  "TARGET_V850E_UP"
   "divh %2,%0,%3"
   [(set_attr "length" "4")
    (set_attr "cc" "clobber")
@@ -715,7 +754,7 @@
 	(umod:HI (match_dup 1)
 		 (match_dup 2)))
    (clobber (reg:CC CC_REGNUM))]
-  "TARGET_V850E || TARGET_V850E2_ALL"
+  "TARGET_V850E_UP"
   "zxh %0 ; divhu %2,%0,%3"
   [(set_attr "length" "4")
    (set_attr "cc" "clobber")
@@ -984,6 +1023,17 @@
 ;; optimize_bitfield_compare in fold-const usually converts single
 ;; bit extracts into an AND with a mask.
 
+(define_insn "insv"
+  [(set (zero_extract:SI (match_operand:SI 0 "register_operand" "+r")
+			 (match_operand:SI 1 "immediate_operand" "n")
+			 (match_operand:SI 2 "immediate_operand" "n"))
+	(match_operand:SI 3 "register_operand" "r"))]
+  "TARGET_V850E3V5_UP"
+  "bins %3, %2, %1, %0"
+  [(set_attr "length" "4")
+   (set_attr "cc" "set_zn")]
+)
+
 ;; -----------------------------------------------------------------
 ;; Scc INSTRUCTIONS
 ;; -----------------------------------------------------------------
@@ -1018,7 +1068,7 @@
 (define_insn "set_z_insn"
   [(set (match_operand:SI 0 "register_operand" "=r")
 	(match_operand 1 "v850_float_z_comparison_operator" ""))]
-  "TARGET_V850E2V3"
+  "TARGET_V850E2V3_UP"
   "setf z,%0"
   [(set_attr "length" "4")
    (set_attr "cc" "none_0hit")])
@@ -1026,7 +1076,7 @@
 (define_insn "set_nz_insn" 
   [(set (match_operand:SI 0 "register_operand" "=r")
 	(match_operand 1 "v850_float_nz_comparison_operator" ""))]
-  "TARGET_V850E2V3"
+  "TARGET_V850E2V3_UP"
   "setf nz,%0"
   [(set_attr "length" "4")
    (set_attr "cc" "none_0hit")])
@@ -1045,7 +1095,7 @@
 	 (match_operand 1 "comparison_operator")
 	 (match_operand:SI 2 "reg_or_const_operand" "rJ")
 	 (match_operand:SI 3 "reg_or_const_operand" "rI")))]
-  "(TARGET_V850E || TARGET_V850E2_ALL)"
+  "(TARGET_V850E_UP)"
   {
     /* Make sure that we have an integer comparison...  */
     if (GET_MODE (XEXP (operands[1], 0)) != CCmode
@@ -1093,7 +1143,7 @@
                          [(reg:CC CC_REGNUM) (const_int 0)])
          (match_operand:SI 2 "reg_or_int5_operand" "rJ")
          (match_operand:SI 3 "reg_or_0_operand" "rI")))]
-  "(TARGET_V850E || TARGET_V850E2_ALL)"
+  "(TARGET_V850E_UP)"
   "cmov %c1,%2,%z3,%0";
   [(set_attr "length" "6")
    (set_attr "cc" "compare")])
@@ -1105,7 +1155,7 @@
                          [(reg:CC CC_REGNUM) (const_int 0)])
          (match_operand:SI 2 "reg_or_0_operand" "rI")
          (match_operand:SI 3 "reg_or_int5_operand" "rJ")))]
-  "(TARGET_V850E || TARGET_V850E2_ALL)"
+  "(TARGET_V850E_UP)"
   "cmov %C1,%3,%z2,%0"
   [(set_attr "length" "6")
    (set_attr "cc" "compare")])
@@ -1118,7 +1168,7 @@
 			  (match_operand:SI 5 "reg_or_int5_operand" "rJ")])
 	 (match_operand:SI 2 "reg_or_int5_operand" "rJ")
 	 (match_operand:SI 3 "reg_or_0_operand" "rI")))]
-  "(TARGET_V850E || TARGET_V850E2_ALL)"
+  "(TARGET_V850E_UP)"
   "cmp %5,%4 ; cmov %c1,%2,%z3,%0"
   [(set_attr "length" "6")
    (set_attr "cc" "clobber")])
@@ -1131,7 +1181,7 @@
 			  (match_operand:SI 5 "reg_or_int5_operand" "rJ")])
 	 (match_operand:SI 2 "reg_or_0_operand" "rI")
 	 (match_operand:SI 3 "reg_or_int5_operand" "rJ")))]
-  "(TARGET_V850E || TARGET_V850E2_ALL)"
+  "(TARGET_V850E_UP)"
   "cmp %5,%4 ; cmov %C1,%3,%z2,%0"
   [(set_attr "length" "6")
    (set_attr "cc" "clobber")])
@@ -1147,7 +1197,7 @@
 			  (const_int 0)])
 	 (match_operand:SI 4 "reg_or_int5_operand" "rJ")
 	 (match_operand:SI 5 "reg_or_0_operand" "rI")))]
-  "(TARGET_V850E || TARGET_V850E2_ALL)"
+  "(TARGET_V850E_UP)"
   "tst1 %3,%2 ; cmov %c1,%4,%z5,%0"
   [(set_attr "length" "8")
    (set_attr "cc" "clobber")])
@@ -1163,7 +1213,7 @@
 			  (const_int 0)])
 	 (match_operand:SI 4 "reg_or_0_operand" "rI")
 	 (match_operand:SI 5 "reg_or_int5_operand" "rJ")))]
-  "(TARGET_V850E || TARGET_V850E2_ALL)"
+  "(TARGET_V850E_UP)"
   "tst1 %3,%2 ; cmov %C1,%5,%z4,%0"
   [(set_attr "length" "8")
    (set_attr "cc" "clobber")])
@@ -1182,7 +1232,7 @@
 	 (ashift:SI (match_operand:SI 2 "register_operand" "0")
 		    (const_int 1))))
    (clobber (reg:CC CC_REGNUM))]
-  "(TARGET_V850E || TARGET_V850E2_ALL)"
+  "(TARGET_V850E_UP)"
   "cmp %4,%3 ; sasf %c1,%0"
   [(set_attr "length" "6")
    (set_attr "cc" "clobber")])
@@ -1196,7 +1246,7 @@
 	 (match_operand:SI 2 "const_int_operand" "")
 	 (match_operand:SI 3 "const_int_operand" "")))
    (clobber (reg:CC CC_REGNUM))]
-  "(TARGET_V850E || TARGET_V850E2_ALL)
+  "(TARGET_V850E_UP)
    && ((INTVAL (operands[2]) ^ INTVAL (operands[3])) == 1)
    && ((INTVAL (operands[2]) + INTVAL (operands[3])) != 1)
    && (GET_CODE (operands[5]) == CONST_INT
@@ -1225,7 +1275,7 @@
 		   (rotate:HI (match_operand:HI 1 "register_operand" "")
 			      (match_operand:HI 2 "const_int_operand" "")))
 	      (clobber (reg:CC CC_REGNUM))])]
-  "(TARGET_V850E || TARGET_V850E2_ALL)"
+  "(TARGET_V850E_UP)"
   {
     if (INTVAL (operands[2]) != 8)
       FAIL;
@@ -1236,7 +1286,7 @@
 	(rotate:HI (match_operand:HI 1 "register_operand" "r")
 		   (const_int 8)))
    (clobber (reg:CC CC_REGNUM))]
-  "(TARGET_V850E || TARGET_V850E2_ALL)"
+  "(TARGET_V850E_UP)"
   "bsh %1,%0"
   [(set_attr "length" "4")
    (set_attr "cc" "clobber")])
@@ -1246,18 +1296,55 @@
 		   (rotate:SI (match_operand:SI 1 "register_operand" "")
 			      (match_operand:SI 2 "const_int_operand" "")))
 	      (clobber (reg:CC CC_REGNUM))])]
-  "(TARGET_V850E || TARGET_V850E2_ALL)"
+  "(TARGET_V850E_UP)"
   {
     if (INTVAL (operands[2]) != 16)
       FAIL;
   })
 
+(define_insn "rotlsi3_a"
+  [(set (match_operand:SI 0 "register_operand" "=r")
+     (match_operator:SI 4 "ior_operator"
+       [(ashift:SI (match_operand:SI 1 "register_operand" "r")
+		   (match_operand:SI 2 "const_int_operand" "n"))
+	(lshiftrt:SI (match_dup 1)
+	(match_operand:SI 3 "const_int_operand" "n"))]))]
+  "TARGET_V850E3V5_UP && (INTVAL (operands[2]) + INTVAL (operands[3]) == 32)"
+  "rotl %2, %1, %0"
+  [(set_attr "length" "4")
+   (set_attr "cc" "set_zn")]
+)
+
+(define_insn "rotlsi3_b"
+  [(set (match_operand:SI 0 "register_operand" "=r")
+     (match_operator:SI 4 "ior_operator"
+       [(lshiftrt:SI (match_operand:SI 1 "register_operand" "r")
+		     (match_operand:SI 3 "const_int_operand" "n"))
+	(ashift:SI (match_dup 1)
+		   (match_operand:SI 2 "const_int_operand" "n"))]))]
+  "TARGET_V850E3V5_UP && (INTVAL (operands[2]) + INTVAL (operands[3]) == 32)"
+  "rotl %2, %1, %0"
+  [(set_attr "length" "4")
+   (set_attr "cc" "set_zn")]
+)
+
+(define_insn "rotlsi3_v850e3v5"
+  [(set (match_operand:SI 0 "register_operand" "=r")
+	(rotate:SI (match_operand:SI 1 "register_operand" "r")
+		   (match_operand:SI 2 "e3v5_shift_operand" "rn")))
+	      (clobber (reg:CC CC_REGNUM))]
+  "TARGET_V850E3V5_UP"
+  "rotl %2, %1, %0"
+  [(set_attr "length" "4")
+   (set_attr "cc" "set_zn")]
+)
+
 (define_insn "*rotlsi3_16"
   [(set (match_operand:SI 0 "register_operand" "=r")
 	(rotate:SI (match_operand:SI 1 "register_operand" "r")
 		   (const_int 16)))
    (clobber (reg:CC CC_REGNUM))]
-  "(TARGET_V850E || TARGET_V850E2_ALL)"
+  "(TARGET_V850E_UP)"
   "hsw %1,%0"
   [(set_attr "length" "4")
    (set_attr "cc" "clobber")])
@@ -1266,6 +1353,99 @@
 ;; JUMP INSTRUCTIONS
 ;; ----------------------------------------------------------------------
 
+;; Doloop
+
+(define_expand "doloop_begin"
+ [(use (match_operand 0 "" ""))        ; loop pseudo
+  (use (match_operand 1 "" ""))        ; iterations; zero if unknown
+  (use (match_operand 2 "" ""))        ; max iterations
+  (use (match_operand 3 "" ""))        ; loop level
+  (use (match_operand 4 "" ""))]       ; condition
+  "TARGET_V850E3V5_UP && TARGET_LOOP"
+  {
+    rtx loop_cnt   = operands[0];
+    rtx loop_level = operands[3];
+
+    if (INTVAL (loop_level) > 1)
+      FAIL;
+    if (GET_MODE (loop_cnt) != SImode)
+      FAIL;
+
+    emit_insn (gen_fix_loop_counter (loop_cnt));
+    DONE;
+  }
+)
+
+(define_insn "fix_loop_counter"
+  [(unspec:SI [(match_operand:SI          0 "register_operand" "+r,!m")
+	       (clobber (match_scratch:SI 1                    "=X,r"))] UNSPEC_LOOP)]
+  "TARGET_V850E3V5_UP && TARGET_LOOP"
+  {
+    switch (which_alternative)
+    {
+    case 0:  return "add 1, %0 # LOOP_BEGIN";
+    case 1:  return "ld.w %0, %1; add 1, %1; st.w %1, %0 # LOOP_BEGIN";
+    default: gcc_unreachable ();
+    }
+  }
+  [(set_attr "length" "2,6")
+   (set_attr "cc" "none")]
+)
+
+(define_expand "doloop_end"
+ [(use (match_operand 0 "" ""))        ; loop pseudo
+  (use (match_operand 1 "" ""))        ; iterations; zero if unknown
+  (use (match_operand 2 "" ""))        ; max iterations
+  (use (match_operand 3 "" ""))        ; loop level
+  (use (match_operand 4 "" ""))        ; label
+  (use (match_operand 5 "" ""))]       ; entered at top
+  "TARGET_V850E3V5_UP && TARGET_LOOP"
+  {
+    rtx loop_cnt   = operands[0];
+    rtx loop_level = operands[3];
+    rtx label      = operands[4];
+
+    if (INTVAL (loop_level) > 1)
+      FAIL;
+    if (GET_MODE (loop_cnt) != SImode)
+      FAIL;
+
+    emit_jump_insn (gen_doloop_end_internal_loop (label, loop_cnt));
+    DONE;
+  }
+)
+
+(define_insn "doloop_end_internal_loop"
+ [(set (pc)
+       (if_then_else (ne (match_operand:SI 1 "register_operand" "+r,!m")
+			 (const_int 0))
+		     (label_ref (match_operand 0 "" ""))
+		     (pc)))
+  (set (match_dup 1) (plus:SI (match_dup 1) (const_int -1)))
+  (clobber (match_scratch:SI 2 "=X,r"))
+  (clobber (reg:CC CC_REGNUM))]
+  "TARGET_V850E3V5_UP && TARGET_LOOP"
+  {
+    switch (which_alternative)
+    {
+    case 0:
+      if (get_attr_length (insn) == 4)
+	return "loop %1, %0 # LOOP.1.0";
+
+      return "add -1, %1; bne %l0 # LOOP.1.1";
+    case 1:
+      return "ld.w %1, %2; add -1, %2; st.w %2, %1; bne %l0 # LOOP.2.1";
+    default:
+      gcc_unreachable ();
+    }
+  }
+ [(set (attr "length")
+       (if_then_else (lt (abs (minus (match_dup 0) (pc)))
+		     (const_int 65534))
+		     (const_int 4)
+		     (const_int 14)))
+  (set_attr "cc" "none")])
+
 ;; Conditional jump instructions
 
 (define_insn "*branch_normal"
@@ -1285,14 +1465,18 @@
 
   if (get_attr_length (insn) == 2)
     return "b%b1 %l0";
-  else
-    return "b%B1 .+6 ; jr %l0";
+  if (TARGET_V850E3V5_UP && get_attr_length (insn) == 4)
+    return "b%b1 %l0";
+  return "b%B1 .+6 ; jr %l0";
 }
  [(set (attr "length")
     (if_then_else (lt (abs (minus (match_dup 0) (pc)))
 		      (const_int 256))
 		  (const_int 2)
-		  (const_int 6)))
+		  (if_then_else (lt (abs (minus (match_dup 0) (pc)))
+		      (const_int 65536))
+		      (const_int 4)
+		      (const_int 6))))
   (set_attr "cc" "none")])
 
 (define_insn "*branch_invert"
@@ -1308,17 +1492,24 @@
 	  || GET_CODE (operands[1]) == GE
 	  || GET_CODE (operands[1]) == LE
 	  || GET_CODE (operands[1]) == LT))
-    return 0;
+    return NULL;
+
   if (get_attr_length (insn) == 2)
     return "b%B1 %l0";
-  else
-    return "b%b1 .+6 ; jr %l0";
+
+  if (TARGET_V850E3V5_UP && get_attr_length (insn) == 4)
+    return "b%B1 %l0";
+    
+  return "b%b1 .+6 ; jr %l0";
 }
  [(set (attr "length")
     (if_then_else (lt (abs (minus (match_dup 0) (pc)))
 		      (const_int 256))
 		  (const_int 2)
-		  (const_int 6)))
+		  (if_then_else (lt (abs (minus (match_dup 0) (pc)))
+		      (const_int 65536))
+		      (const_int 4)
+		      (const_int 6))))
   (set_attr "cc" "none")])
 
 (define_insn "branch_z_normal"	
@@ -1326,18 +1517,24 @@
 	(if_then_else (match_operand 1 "v850_float_z_comparison_operator" "")
 		      (label_ref (match_operand 0 "" ""))
 		      (pc)))]
-  "TARGET_V850E2V3"
+  "TARGET_V850E2V3_UP"
 {
   if (get_attr_length (insn) == 2)
     return "bz %l0";
-  else
-    return "bnz 1f ; jr %l0 ; 1:";
+
+  if (TARGET_V850E3V5_UP && get_attr_length (insn) == 4)
+    return "bz %l0";
+
+  return "bnz 1f ; jr %l0 ; 1:";
 }
  [(set (attr "length")
     (if_then_else (lt (abs (minus (match_dup 0) (pc)))
 		      (const_int 256))
 		  (const_int 2)
-		  (const_int 6)))
+		  (if_then_else (lt (abs (minus (match_dup 0) (pc)))
+		      (const_int 65536))
+		      (const_int 4)
+		      (const_int 6))))
   (set_attr "cc" "none")])
 
 (define_insn "*branch_z_invert"
@@ -1345,18 +1542,24 @@
 	(if_then_else (match_operand 1 "v850_float_z_comparison_operator" "")
 		      (pc)
 		      (label_ref (match_operand 0 "" ""))))]
-  "TARGET_V850E2V3"
+  "TARGET_V850E2V3_UP"
 {
   if (get_attr_length (insn) == 2)
     return "bnz %l0";
-  else
-    return "bz 1f ; jr %l0 ; 1:";
+
+  if (TARGET_V850E3V5_UP && get_attr_length (insn) == 4)
+    return "bnz %l0";
+
+  return "bz 1f ; jr %l0 ; 1:";
 }
  [(set (attr "length")
     (if_then_else (lt (abs (minus (match_dup 0) (pc)))
 			   (const_int 256))
 		  (const_int 2)
-		  (const_int 6)))
+		  (if_then_else (lt (abs (minus (match_dup 0) (pc)))
+		      (const_int 65536))
+		      (const_int 4)
+		      (const_int 6))))
   (set_attr "cc" "none")])
 
 (define_insn "branch_nz_normal"
@@ -1364,18 +1567,24 @@
 	(if_then_else (match_operand 1 "v850_float_nz_comparison_operator" "")
 		      (label_ref (match_operand 0 "" ""))
 		      (pc)))]
-  "TARGET_V850E2V3"
+  "TARGET_V850E2V3_UP"
 {
   if (get_attr_length (insn) == 2)
     return "bnz %l0";
-  else
-    return "bz 1f ; jr %l0 ; 1:";
+
+  if (TARGET_V850E3V5_UP && get_attr_length (insn) == 4)
+    return "bnz %l0";
+
+  return "bz 1f ; jr %l0 ; 1:";
 }
 [(set (attr "length")
     (if_then_else (lt (abs (minus (match_dup 0) (pc)))
 			   (const_int 256))
 		  (const_int 2)
-		  (const_int 6)))
+		  (if_then_else (lt (abs (minus (match_dup 0) (pc)))
+		      (const_int 65536))
+		      (const_int 4)
+		      (const_int 6))))
   (set_attr "cc" "none")])
 
 (define_insn "*branch_nz_invert"
@@ -1383,18 +1592,24 @@
 	(if_then_else (match_operand 1 "v850_float_nz_comparison_operator" "")
 		      (pc)
 		      (label_ref (match_operand 0 "" ""))))]
-  "TARGET_V850E2V3"
+  "TARGET_V850E2V3_UP"
 {
   if (get_attr_length (insn) == 2)
     return "bz %l0";
-  else
-    return "bnz 1f ; jr %l0 ; 1:";
+
+  if (TARGET_V850E3V5_UP && get_attr_length (insn) == 4)
+    return "bz %l0";
+
+  return "bnz 1f ; jr %l0 ; 1:";
 }
  [(set (attr "length")
     (if_then_else (lt (abs (minus (match_dup 0) (pc)))
 		      (const_int 256))
 		  (const_int 2)
-		  (const_int 6)))
+		  (if_then_else (lt (abs (minus (match_dup 0) (pc)))
+		      (const_int 65536))
+		      (const_int 4)
+		      (const_int 6))))
   (set_attr "cc" "none")])
 
 ;; Unconditional and other jump instructions.
@@ -1440,7 +1655,7 @@
 			      (const_int 1))
 		   (label_ref (match_operand 1 "" "")))))
 	(label_ref (match_dup 1))))]
-  "(TARGET_V850E || TARGET_V850E2_ALL)"
+  "(TARGET_V850E_UP)"
   "switch %0"
   [(set_attr "length" "2")
    (set_attr "cc" "none")])
@@ -1512,9 +1727,17 @@
 	 (match_operand:SI 1 "general_operand" "g,g"))
    (clobber (reg:SI 31))]
   "! TARGET_LONG_CALLS"
-  "@
-  jarl %0,r31
-  jarl .+4,r31 ; add 4,r31 ; jmp %0"
+  {
+    if (which_alternative == 1)
+      {
+        if (TARGET_V850E3V5_UP)
+	  return "jarl [%0], r31";
+
+        return "jarl .+4, r31 ; add 4, r31 ; jmp %0";
+      }
+
+    return "jarl %0, r31";
+  }
   [(set_attr "length" "4,8")
    (set_attr "cc" "clobber,clobber")]
 )
@@ -1529,11 +1752,17 @@
     {
       if (GET_CODE (operands[0]) == REG)
         return "jarl %0,r31";
-      else
-        return "movhi hi(%0), r0, r11 ; movea lo(%0), r11, r11 ; jarl .+4,r31 ; add 4, r31 ; jmp r11";
+
+      if (TARGET_V850E3V5_UP)
+	return "mov hilo(%0), r11 ; jarl [r11], r31";
+
+      return "movhi hi(%0), r0, r11 ; movea lo(%0), r11, r11 ; jarl .+4,r31 ; add 4, r31 ; jmp r11";
     }
-  else
-    return "jarl .+4,r31 ; add 4,r31 ; jmp %0";
+
+  if (TARGET_V850E3V5_UP)
+    return "jarl [%0], r31";
+
+  return "jarl .+4,r31 ; add 4,r31 ; jmp %0";
 }
   [(set_attr "length" "16,8")
    (set_attr "cc" "clobber,clobber")]
@@ -1568,9 +1797,17 @@
 	      (match_operand:SI 2 "general_operand" "g,g")))
    (clobber (reg:SI 31))]
   "! TARGET_LONG_CALLS"
-  "@
-  jarl %1,r31
-  jarl .+4,r31 ; add 4,r31 ; jmp %1"
+  {
+    if (which_alternative == 1)
+      {
+        if (TARGET_V850E3V5_UP)
+          return "jarl [%1], r31";
+
+        return "jarl .+4, r31 ; add 4, r31 ; jmp %1";
+      }
+
+    return "jarl %1, r31";
+  }
   [(set_attr "length" "4,8")
    (set_attr "cc" "clobber,clobber")]
 )
@@ -1586,12 +1823,18 @@
     {
       if (GET_CODE (operands[1]) == REG)
         return "jarl %1, r31";
-      else
+
       /* Reload can generate this pattern....  */
-        return "movhi hi(%1), r0, r11 ; movea lo(%1), r11, r11 ; jarl .+4, r31 ; add 4, r31 ; jmp r11";
+      if (TARGET_V850E3V5_UP)
+        return "mov hilo(%1), r11 ; jarl [r11], r31";
+
+      return "movhi hi(%1), r0, r11 ; movea lo(%1), r11, r11 ; jarl .+4, r31 ; add 4, r31 ; jmp r11";
     }
-  else
-    return "jarl .+4, r31 ; add 4, r31 ; jmp %1";
+  
+  if (TARGET_V850E3V5_UP)
+    return "jarl [%1], r31";
+
+  return "jarl .+4, r31 ; add 4, r31 ; jmp %1";
 }
   [(set_attr "length" "16,8")
    (set_attr "cc" "clobber,clobber")]
@@ -1613,7 +1856,7 @@
 	(zero_extend:SI
         (match_operand:HI 1 "nonimmediate_operand" "0,r,T,m")))
    (clobber (reg:CC CC_REGNUM))]
-  "(TARGET_V850E || TARGET_V850E2_ALL)"
+  "(TARGET_V850E_UP)"
   "@
    zxh %0
    andi 65535,%1,%0
@@ -1639,7 +1882,7 @@
 	      (clobber (reg:CC CC_REGNUM))])]
   ""
   {
-    if (! (TARGET_V850E || TARGET_V850E2_ALL))
+    if (! (TARGET_V850E_UP))
       operands[1] = force_reg (HImode, operands[1]);
   })
 
@@ -1648,7 +1891,7 @@
 	(zero_extend:SI
 	(match_operand:QI 1 "nonimmediate_operand" "0,r,T,m")))
    (clobber (reg:CC CC_REGNUM))]
-  "(TARGET_V850E || TARGET_V850E2_ALL)"
+  "(TARGET_V850E_UP)"
   "@
    zxb %0
    andi 255,%1,%0
@@ -1674,7 +1917,7 @@
 	      (clobber (reg:CC CC_REGNUM))])]
   ""
   {
-    if (! (TARGET_V850E || TARGET_V850E2_ALL))
+    if (! (TARGET_V850E_UP))
       operands[1] = force_reg (QImode, operands[1]);
   })
 
@@ -1686,7 +1929,7 @@
   [(set (match_operand:SI 0 "register_operand" "=r,r,r")
 	(sign_extend:SI (match_operand:HI 1 "nonimmediate_operand" "0,Q,m")))
    (clobber (reg:CC CC_REGNUM))]
-  "(TARGET_V850E || TARGET_V850E2_ALL)"
+  "(TARGET_V850E_UP)"
   "@
    sxh %0
    sld.h %1,%0
@@ -1718,7 +1961,7 @@
   [(set (match_operand:SI 0 "register_operand" "=r,r,r")
 	(sign_extend:SI (match_operand:QI 1 "nonimmediate_operand" "0,Q,m")))
    (clobber (reg:CC CC_REGNUM))]
-  "(TARGET_V850E || TARGET_V850E2_ALL)"
+  "(TARGET_V850E_UP)"
   "@
    sxb %0
    sld.b %1,%0
@@ -1767,7 +2010,7 @@
 	(match_operand:SI 1 "register_operand" "r")
 	(match_operand:SI 2 "nonmemory_operand" "r")))
    (clobber (reg:CC CC_REGNUM))]
-  "TARGET_V850E2_ALL"
+  "TARGET_V850E2_UP"
   "shl %2,%1,%0"
   [(set_attr "length" "4")
    (set_attr "cc" "set_znv")])
@@ -1791,7 +2034,7 @@
 	(match_operand:SI 1 "register_operand" "r")
 	(match_operand:SI 2 "nonmemory_operand" "r")))
    (clobber (reg:CC CC_REGNUM))]
-  "TARGET_V850E2_ALL"
+  "TARGET_V850E2_UP"
   "shr %2,%1,%0"
   [(set_attr "length" "4")
    (set_attr "cc" "set_zn")])
@@ -1815,7 +2058,7 @@
 	(match_operand:SI 1 "register_operand" "r")
 	(match_operand:SI 2 "nonmemory_operand" "r")))
    (clobber (reg:CC CC_REGNUM))]
-  "TARGET_V850E2_ALL"
+  "TARGET_V850E2_UP"
   "sar %2,%1,%0"
   [(set_attr "length" "4")
    (set_attr "cc" "set_zn")])
@@ -1828,7 +2071,7 @@
   [(set (match_operand:SI 0 "register_operand" "=r")
        (ffs:SI (match_operand:SI 1 "register_operand" "r")))
    (clobber (reg:CC CC_REGNUM))]
-  "TARGET_V850E2_ALL"
+  "TARGET_V850E2_UP"
   "sch1r %1,%0"
   [(set_attr "length" "4")
    (set_attr "cc" "clobber")])
@@ -2529,7 +2772,7 @@
     (set (mem:SI (plus:SI (reg:SI 3)
 			  (match_operand:SI 2 "immediate_operand" "i")))
 	 (match_operand:SI 3 "register_is_ok_for_epilogue" "r"))])]
- "TARGET_PROLOG_FUNCTION && (TARGET_V850E || TARGET_V850E2_ALL)"
+ "TARGET_PROLOG_FUNCTION && (TARGET_V850E_UP)"
 {
   return construct_prepare_instruction (operands[0]);
 }
@@ -2563,7 +2806,7 @@
     (set (match_operand:SI 2 "register_is_ok_for_epilogue" "=r")
 	 (mem:SI (plus:SI (reg:SI 3)
 			  (match_operand:SI 3 "immediate_operand" "i"))))])]
- "TARGET_PROLOG_FUNCTION && (TARGET_V850E || TARGET_V850E2_ALL)"
+ "TARGET_PROLOG_FUNCTION && (TARGET_V850E_UP)"
 {
   return construct_dispose_instruction (operands[0]);
 }
@@ -2594,7 +2837,7 @@
 ;; Initialize an interrupt function.  Do not depend on TARGET_PROLOG_FUNCTION.
 (define_insn "callt_save_interrupt"
   [(unspec_volatile [(const_int 0)] 2)]
-    "(TARGET_V850E || TARGET_V850E2_ALL) && !TARGET_DISABLE_CALLT"
+    "(TARGET_V850E_UP) && !TARGET_DISABLE_CALLT"
     ;; The CALLT instruction stores the next address of CALLT to CTPC register
     ;; without saving its previous value.  So if the interrupt handler
     ;; or its caller could possibly execute the CALLT insn, save_interrupt 
@@ -2616,7 +2859,7 @@
 
 (define_insn "callt_return_interrupt"
   [(unspec_volatile [(const_int 0)] 3)]
-  "(TARGET_V850E || TARGET_V850E2_ALL) && !TARGET_DISABLE_CALLT"
+  "(TARGET_V850E_UP) && !TARGET_DISABLE_CALLT"
   "callt ctoff(__callt_return_interrupt)"
   [(set_attr "length" "2")
    (set_attr "cc" "clobber")])
@@ -2693,7 +2936,7 @@
 
 (define_insn "callt_save_all_interrupt"
   [(unspec_volatile [(const_int 0)] 0)]
-  "(TARGET_V850E || TARGET_V850E2_ALL) && !TARGET_DISABLE_CALLT"
+  "(TARGET_V850E_UP) && !TARGET_DISABLE_CALLT"
   "callt ctoff(__callt_save_all_interrupt)"
   [(set_attr "length" "2")
    (set_attr "cc" "none")])
@@ -2793,7 +3036,7 @@
 
 (define_insn "callt_restore_all_interrupt"
   [(unspec_volatile [(const_int 0)] 1)]
-  "(TARGET_V850E || TARGET_V850E2_ALL) && !TARGET_DISABLE_CALLT"
+  "(TARGET_V850E_UP) && !TARGET_DISABLE_CALLT"
   "callt ctoff(__callt_restore_all_interrupt)"
   [(set_attr "length" "2")
    (set_attr "cc" "none")])
diff --git a/gcc/config/v850/v850.opt b/gcc/config/v850/v850.opt
index 4418c0b19f30..feba0ddc27a3 100644
--- a/gcc/config/v850/v850.opt
+++ b/gcc/config/v850/v850.opt
@@ -112,6 +112,17 @@ mv850e2v3
 Target Report RejectNegative Mask(V850E2V3)
 Compile for the v850e2v3 processor
 
+mv850e3v5
+Target Report RejectNegative Mask(V850E3V5)
+Compile for the v850e3v5 processor
+
+mv850e2v4
+Target RejectNegative Mask(V850E3V5) MaskExists
+
+mloop
+Target Report Mask(LOOP)
+Enable v850e3v5 loop instructions
+
 mzda=
 Target RejectNegative Joined UInteger
 Set the max size of data eligible for the ZDA area
diff --git a/gcc/doc/invoke.texi b/gcc/doc/invoke.texi
index ef06b0b28518..e9fe4efe9788 100644
--- a/gcc/doc/invoke.texi
+++ b/gcc/doc/invoke.texi
@@ -956,11 +956,16 @@ See RS/6000 and PowerPC Options.
 -mtda=@var{n}  -msda=@var{n}  -mzda=@var{n} @gol
 -mapp-regs  -mno-app-regs @gol
 -mdisable-callt  -mno-disable-callt @gol
--mv850e2v3 @gol
--mv850e2 @gol
--mv850e1 -mv850es @gol
--mv850e @gol
--mv850  -mbig-switch}
+-mv850e2v3 -mv850e2 -mv850e1 -mv850es @gol
+-mv850e -mv850 -mv850e3v5 @gol
+-mloop @gol
+-mrelax @gol
+-mlong-jumps @gol
+-msoft-float @gol
+-mhard-float @gol
+-mgcc-abi @gol
+-mrh850-abi @gol
+-mbig-switch}
 
 @emph{VAX Options}
 @gccoptlist{-mg  -mgnu  -munix}
@@ -6083,7 +6088,7 @@ vectorizer passes print the source location of loops which got
 successfully vectorized.
 @item missed
 Print information about missed optimizations. Individual passes
-control which informations to include in the output. For example,
+control which information to include in the output. For example,
 
 @smallexample
 gcc -O2 -ftree-vectorize -fopt-info-vec-missed
@@ -8401,7 +8406,7 @@ requires the complete toolchain to be aware of LTO. It requires a linker with
 linker plugin support for basic functionality.  Additionally,
 @command{nm}, @command{ar} and @command{ranlib}
 need to support linker plugins to allow a full-featured build environment
-(capable of building static libraries etc). gcc provides the @command{gcc-ar},
+(capable of building static libraries etc).  GCC provides the @command{gcc-ar},
 @command{gcc-nm}, @command{gcc-ranlib} wrappers to pass the right options
 to these tools. With non fat LTO makefiles need to be modified to use them.
 
@@ -19591,26 +19596,20 @@ the first 32 kilobytes of memory.
 @opindex mv850
 Specify that the target processor is the V850.
 
-@item -mbig-switch
-@opindex mbig-switch
-Generate code suitable for big switch tables.  Use this option only if
-the assembler/linker complain about out of range branches within a switch
-table.
-
-@item -mapp-regs
-@opindex mapp-regs
-This option causes r2 and r5 to be used in the code generated by
-the compiler.  This setting is the default.
+@item -mv850e3v5
+@opindex mv850e3v5
+Specify that the target processor is the V850E3V5.  The preprocessor
+constant @samp{__v850e3v5__} is defined if this option is used.
 
-@item -mno-app-regs
-@opindex mno-app-regs
-This option causes r2 and r5 to be treated as fixed registers.
+@item -mv850e2v4
+@opindex mv850e2v4
+Specify that the target processor is the V850E3V5.  This is an alias for
+the @option{-mv850e3v5} option.
 
 @item -mv850e2v3
 @opindex mv850e2v3
 Specify that the target processor is the V850E2V3.  The preprocessor
-constant @samp{__v850e2v3__} is defined if
-this option is used.
+constant @samp{__v850e2v3__} is defined if this option is used.
 
 @item -mv850e2
 @opindex mv850e2
@@ -19634,7 +19633,7 @@ Specify that the target processor is the V850E@.  The preprocessor
 constant @samp{__v850e__} is defined if this option is used.
 
 If neither @option{-mv850} nor @option{-mv850e} nor @option{-mv850e1}
-nor @option{-mv850e2} nor @option{-mv850e2v3}
+nor @option{-mv850e2} nor @option{-mv850e2v3} nor @option{-mv850e3v5}
 are defined then a default target processor is chosen and the
 relevant @samp{__v850*__} preprocessor constant is defined.
 
@@ -19642,10 +19641,131 @@ The preprocessor constants @samp{__v850} and @samp{__v851__} are always
 defined, regardless of which processor variant is the target.
 
 @item -mdisable-callt
+@itemx -mno-disable-callt
 @opindex mdisable-callt
+@opindex mno-disable-callt
 This option suppresses generation of the @code{CALLT} instruction for the
-v850e, v850e1, v850e2 and v850e2v3 flavors of the v850 architecture.  The default is
-@option{-mno-disable-callt} which allows the @code{CALLT} instruction to be used.
+v850e, v850e1, v850e2, v850e2v3 and v850e3v5 flavors of the v850
+architecture.
+
+This option is enabled by default when the RH850 ABI is
+in use (see @option{-mrh850-abi}), and disabled by default when the
+GCC ABI is in use.  If @code{CALLT} instructions are being generated
+then the C preprocessor symbol @code{__V850_CALLT__} will be defined.
+
+@item -mrelax
+@itemx -mno-relax
+@opindex mrelax
+@opindex mno-relax
+Pass on (or do not pass on) the @option{-mrelax} command line option
+to the assembler.
+
+@item -mlong-jumps
+@itemx -mno-long-jumps
+@opindex mlong-jumps
+@opindex mno-long-jumps
+Disable (or re-enable) the generation of PC-relative jump instructions.
+
+@item -msoft-float
+@itemx -mhard-float
+@opindex msoft-float
+@opindex mhard-float
+Disable (or re-enable) the generation of hardware floating point
+instructions.  This option is only significant when the target
+architecture is @samp{V850E2V3} or higher.  If hardware floating point
+instructions are being generated then the C preprocessor symbol
+@code{__FPU_OK__} will be defined, otherwise the symbol
+@code{__NO_FPU__} will be defined.
+
+@item -mloop
+@opindex mloop
+Enables the use of the e3v5 LOOP instruction.  The use of this
+instruction is not enabled by default when the e3v5 architecture is
+selected because its use is still experimental.
+
+@item -mrh850-abi
+@itemx -mghs
+@opindex mrh850-abi
+@opindex mghs
+Enables support for the RH850 version of the V850 ABI.  This is the
+default.  With this version of the ABI the following rules apply:
+
+@itemize
+@item
+Integer sized structures and unions are returned via a memory pointer
+rather than a register.
+
+@item
+Large structures and unions (more than 8 bytes in size) are passed by
+value.
+
+@item
+Functions are aligned to 16-bit boundaries.
+
+@item
+The @option{-m8byte-align} command line option is supported.
+
+@item
+The @option{-mdisable-callt} command line option is enabled by
+default.  The @option{-mno-disable-callt} command line option is not
+supported.
+@end itemize
+
+When this version of the ABI is enabled the C preprocessor symbol
+@code{__V850_RH850_ABI__} is defined.
+
+@item -mgcc-abi
+@opindex mgcc-abi
+Enables support for the old GCC version of the V850 ABI.  With this
+version of the ABI the following rules apply:
+
+@itemize
+@item
+Integer sized structures and unions are returned in register @code{r10}.
+
+@item
+Large structures and unions (more than 8 bytes in size) are passed by
+reference.
+
+@item
+Functions are aligned to 32-bit boundaries, unless optimizing for
+size.
+
+@item
+The @option{-m8byte-align} command line option is not supported.
+
+@item
+The @option{-mdisable-callt} command line option is supported but not
+enabled by default.
+@end itemize
+
+When this version of the ABI is enabled the C preprocessor symbol
+@code{__V850_GCC_ABI__} is defined.
+
+@item -m8byte-align
+@itemx -mno-8byte-align
+@opindex m8byte-align
+@opindex mno-8byte-align
+Enables support for @code{doubles} and @code{long long} types to be
+aligned on 8-byte boundaries.  The default is to restrict the
+alignment of all objects to at most 4-bytes.  When
+@option{-m8byte-align} is in effect the C preprocessor symbol
+@code{__V850_8BYTE_ALIGN__} will be defined.
+
+@item -mbig-switch
+@opindex mbig-switch
+Generate code suitable for big switch tables.  Use this option only if
+the assembler/linker complain about out of range branches within a switch
+table.
+
+@item -mapp-regs
+@opindex mapp-regs
+This option causes r2 and r5 to be used in the code generated by
+the compiler.  This setting is the default.
+
+@item -mno-app-regs
+@opindex mno-app-regs
+This option causes r2 and r5 to be treated as fixed registers.
 
 @end table
 
diff --git a/libgcc/ChangeLog b/libgcc/ChangeLog
index 1d7a25b9d6c0..b99f8032fb39 100644
--- a/libgcc/ChangeLog
+++ b/libgcc/ChangeLog
@@ -1,3 +1,8 @@
+2013-01-31  Nick Clifton  <nickc@redhat.com>
+
+	* config/v850/lib1funcs.S: Add support for e3v5 architecture
+	variant.
+
 2013-01-29  Georg-Johann Lay  <avr@gjlay.de>
 
 	PR target/54222
@@ -9,7 +14,7 @@
 
 2013-01-26  David Holsgrove <david.holsgrove@xilinx.com>
 
-	* config.host(microblaze*-linux*): tmake_file: Remove 
+	* config.host(microblaze*-linux*): tmake_file: Remove
 	t-slibgcc-nolc-override, add t-slibgcc-libgcc.
 	* config/microblaze/t-microblaze: Set LIB2FUNCS_EXCLUDE
 	to exclude functions from being built with libgcc.c and use
diff --git a/libgcc/config/v850/lib1funcs.S b/libgcc/config/v850/lib1funcs.S
index 45ef1de7dd8e..ff8a55d51be2 100644
--- a/libgcc/config/v850/lib1funcs.S
+++ b/libgcc/config/v850/lib1funcs.S
@@ -81,7 +81,7 @@ ___mulsi3:
         add   r7,  r10
         jmp   [r31]
 #endif /* __v850__ */
-#if defined(__v850e__) || defined(__v850ea__) || defined(__v850e2__) || defined(__v850e2v3__)
+#if defined(__v850e__) || defined(__v850ea__) || defined(__v850e2__) || defined(__v850e2v3__) || defined(__v850e3v5__)
         /* This routine is almost unneccesarry because gcc
            generates the MUL instruction for the RTX mulsi3.
            But if someone wants to link his application with
@@ -1765,7 +1765,7 @@ __restore_all_interrupt:
 #endif /* L_save_all_interrupt */
 	
 #if defined __V850_CALLT__
-#if defined(__v850e__) || defined(__v850e1__) || defined(__v850e2__) || defined(__v850e2v3__)
+#if defined(__v850e__) || defined(__v850e1__) || defined(__v850e2__) || defined(__v850e2v3__) || defined(__v850e3v5__)
 #ifdef	L_callt_save_r2_r29
 	/* Put these functions into the call table area.  */
 	.call_table_text
@@ -2146,7 +2146,7 @@ __callt_save_r31c:	.short ctoff(.L_callt_save_r31c)
 __callt_return_r31c:	.short ctoff(.L_callt_return_r31c)		
 #endif
 
-#endif /* __v850e__ */
+#endif /* __v850e__ + */
 #endif /* __V850_CALLT__ */
 
 /*  libgcc2 routines for NEC V850.  */
-- 
GitLab