Module Name:    src
Committed By:   matt
Date:           Fri Mar 27 01:51:34 UTC 2015

Modified Files:
        src/external/gpl3/gcc/dist/gcc/common/config/riscv: riscv-common.c
        src/external/gpl3/gcc/dist/gcc/config/riscv: constraints.md elf.h
            linux.h linux64.h opcode-riscv.h peephole.md riscv-opc.h
            riscv-protos.h riscv.c riscv.h riscv.md riscv.opt sync.md t-elf
            t-linux64
Added Files:
        src/external/gpl3/gcc/dist/gcc/config/riscv: default-32.h
Removed Files:
        src/external/gpl3/gcc/dist/gcc/config/riscv: crti.asm crtn.asm div.S
            riscv-fp.c

Log Message:
Update gcc to use new ABI for RISCV


To generate a diff of this commit:
cvs rdiff -u -r1.1 -r1.2 \
    src/external/gpl3/gcc/dist/gcc/common/config/riscv/riscv-common.c
cvs rdiff -u -r1.1 -r1.2 \
    src/external/gpl3/gcc/dist/gcc/config/riscv/constraints.md \
    src/external/gpl3/gcc/dist/gcc/config/riscv/elf.h \
    src/external/gpl3/gcc/dist/gcc/config/riscv/linux.h \
    src/external/gpl3/gcc/dist/gcc/config/riscv/linux64.h \
    src/external/gpl3/gcc/dist/gcc/config/riscv/opcode-riscv.h \
    src/external/gpl3/gcc/dist/gcc/config/riscv/peephole.md \
    src/external/gpl3/gcc/dist/gcc/config/riscv/riscv-opc.h \
    src/external/gpl3/gcc/dist/gcc/config/riscv/riscv-protos.h \
    src/external/gpl3/gcc/dist/gcc/config/riscv/riscv.c \
    src/external/gpl3/gcc/dist/gcc/config/riscv/riscv.h \
    src/external/gpl3/gcc/dist/gcc/config/riscv/riscv.md \
    src/external/gpl3/gcc/dist/gcc/config/riscv/riscv.opt \
    src/external/gpl3/gcc/dist/gcc/config/riscv/t-elf \
    src/external/gpl3/gcc/dist/gcc/config/riscv/t-linux64
cvs rdiff -u -r1.1 -r0 src/external/gpl3/gcc/dist/gcc/config/riscv/crti.asm \
    src/external/gpl3/gcc/dist/gcc/config/riscv/crtn.asm \
    src/external/gpl3/gcc/dist/gcc/config/riscv/div.S \
    src/external/gpl3/gcc/dist/gcc/config/riscv/riscv-fp.c
cvs rdiff -u -r0 -r1.1 \
    src/external/gpl3/gcc/dist/gcc/config/riscv/default-32.h
cvs rdiff -u -r1.2 -r1.3 src/external/gpl3/gcc/dist/gcc/config/riscv/sync.md

Please note that diffs are not public domain; they are subject to the
copyright notices on the relevant files.

Modified files:

Index: src/external/gpl3/gcc/dist/gcc/common/config/riscv/riscv-common.c
diff -u src/external/gpl3/gcc/dist/gcc/common/config/riscv/riscv-common.c:1.1 src/external/gpl3/gcc/dist/gcc/common/config/riscv/riscv-common.c:1.2
--- src/external/gpl3/gcc/dist/gcc/common/config/riscv/riscv-common.c:1.1	Fri Sep 19 17:20:29 2014
+++ src/external/gpl3/gcc/dist/gcc/common/config/riscv/riscv-common.c	Fri Mar 27 01:51:34 2015
@@ -25,16 +25,85 @@ along with GCC; see the file COPYING3.  
 #include "common/common-target-def.h"
 #include "opts.h"
 #include "flags.h"
+#include "errors.h"
+
+/* Parse a RISC-V ISA string into an option mask.  */
+
+static void
+riscv_parse_arch_string (const char *isa, int *flags)
+{
+  const char *p = isa;
+
+  if (strncmp (p, "RV32", 4) == 0)
+    *flags |= MASK_32BIT, p += 4;
+  else if (strncmp (p, "RV64", 4) == 0)
+    *flags &= ~MASK_32BIT, p += 4;
+
+  if (*p++ != 'I')
+    {
+      error ("-march=%s: ISA strings must begin with I, RV32I, or RV64I", isa);
+      return;
+    }
+
+  *flags &= ~MASK_MULDIV;
+  if (*p == 'M')
+    *flags |= MASK_MULDIV, p++;
+
+  *flags &= ~MASK_ATOMIC;
+  if (*p == 'A')
+    *flags |= MASK_ATOMIC, p++;
+
+  *flags |= MASK_SOFT_FLOAT_ABI;
+  if (*p == 'F')
+    *flags &= ~MASK_SOFT_FLOAT_ABI, p++;
+
+  if (*p == 'D')
+    {
+      p++;
+      if (!TARGET_HARD_FLOAT)
+	{
+	  error ("-march=%s: the D extension requires the F extension", isa);
+	  return;
+	}
+    }
+  else if (TARGET_HARD_FLOAT)
+    {
+      error ("-march=%s: single-precision-only is not yet supported", isa);
+      return;
+    }
+
+  if (*p)
+    {
+      error ("-march=%s: unsupported ISA substring %s", isa, p);
+      return;
+    }
+}
+
+static int
+riscv_flags_from_arch_string (const char *isa)
+{
+  int flags = 0;
+  riscv_parse_arch_string (isa, &flags);
+  return flags;
+}
 
 /* Implement TARGET_HANDLE_OPTION.  */
 
 static bool
-riscv_handle_option (struct gcc_options *opts ATTRIBUTE_UNUSED,
+riscv_handle_option (struct gcc_options *opts,
 		     struct gcc_options *opts_set ATTRIBUTE_UNUSED,
-		     const struct cl_decoded_option *decoded ATTRIBUTE_UNUSED,
+		     const struct cl_decoded_option *decoded,
 		     location_t loc ATTRIBUTE_UNUSED)
 {
-  return true;
+  switch (decoded->opt_index)
+    {
+    case OPT_march_:
+      riscv_parse_arch_string (decoded->arg, &opts->x_target_flags);
+      return true;
+
+    default:
+      return true;
+    }
 }
 
 /* Implement TARGET_OPTION_OPTIMIZATION_TABLE.  */
@@ -49,10 +118,10 @@ static const struct default_options risc
 #define TARGET_OPTION_OPTIMIZATION_TABLE riscv_option_optimization_table
 
 #undef TARGET_DEFAULT_TARGET_FLAGS
-#define TARGET_DEFAULT_TARGET_FLAGS		\
-  (TARGET_DEFAULT				\
-   | TARGET_CPU_DEFAULT				\
+#define TARGET_DEFAULT_TARGET_FLAGS				\
+  (riscv_flags_from_arch_string (RISCV_ARCH_STRING_DEFAULT)	\
    | (TARGET_64BIT_DEFAULT ? 0 : MASK_32BIT))
+
 #undef TARGET_HANDLE_OPTION
 #define TARGET_HANDLE_OPTION riscv_handle_option
 

Index: src/external/gpl3/gcc/dist/gcc/config/riscv/constraints.md
diff -u src/external/gpl3/gcc/dist/gcc/config/riscv/constraints.md:1.1 src/external/gpl3/gcc/dist/gcc/config/riscv/constraints.md:1.2
--- src/external/gpl3/gcc/dist/gcc/config/riscv/constraints.md:1.1	Fri Sep 19 17:20:29 2014
+++ src/external/gpl3/gcc/dist/gcc/config/riscv/constraints.md	Fri Mar 27 01:51:34 2015
@@ -60,16 +60,11 @@
   "@internal"
   (match_operand 0 "const_arith_operand"))
 
-(define_memory_constraint "YR"
+(define_memory_constraint "A"
   "An address that is held in a general-purpose register."
   (and (match_code "mem")
        (match_test "GET_CODE(XEXP(op,0)) == REG")))
 
-(define_memory_constraint "R"
-  "An address that can be used in a non-macro load or store."
-  (and (match_code "mem")
-       (match_test "riscv_address_insns (XEXP (op, 0), mode, false) == 1")))
-
 (define_constraint "S"
   "@internal
    A constant call address."
Index: src/external/gpl3/gcc/dist/gcc/config/riscv/elf.h
diff -u src/external/gpl3/gcc/dist/gcc/config/riscv/elf.h:1.1 src/external/gpl3/gcc/dist/gcc/config/riscv/elf.h:1.2
--- src/external/gpl3/gcc/dist/gcc/config/riscv/elf.h:1.1	Fri Sep 19 17:20:29 2014
+++ src/external/gpl3/gcc/dist/gcc/config/riscv/elf.h	Fri Mar 27 01:51:34 2015
@@ -1,4 +1,4 @@
-/* Target macros for mips*-elf targets.
+/* Target macros for riscv*-elf targets.
    Copyright (C) 1994, 1997, 1999, 2000, 2002, 2003, 2004, 2007, 2010
    Free Software Foundation, Inc.
 
Index: src/external/gpl3/gcc/dist/gcc/config/riscv/linux.h
diff -u src/external/gpl3/gcc/dist/gcc/config/riscv/linux.h:1.1 src/external/gpl3/gcc/dist/gcc/config/riscv/linux.h:1.2
--- src/external/gpl3/gcc/dist/gcc/config/riscv/linux.h:1.1	Fri Sep 19 17:20:29 2014
+++ src/external/gpl3/gcc/dist/gcc/config/riscv/linux.h	Fri Mar 27 01:51:34 2015
@@ -1,4 +1,4 @@
-/* Definitions for MIPS running Linux-based GNU systems with ELF format.
+/* Definitions for RISC-V GNU/Linux systems with ELF format.
    Copyright (C) 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006,
    2007, 2008, 2010, 2011 Free Software Foundation, Inc.
 
Index: src/external/gpl3/gcc/dist/gcc/config/riscv/linux64.h
diff -u src/external/gpl3/gcc/dist/gcc/config/riscv/linux64.h:1.1 src/external/gpl3/gcc/dist/gcc/config/riscv/linux64.h:1.2
--- src/external/gpl3/gcc/dist/gcc/config/riscv/linux64.h:1.1	Fri Sep 19 17:20:29 2014
+++ src/external/gpl3/gcc/dist/gcc/config/riscv/linux64.h	Fri Mar 27 01:51:34 2015
@@ -1,5 +1,4 @@
-/* Definitions for MIPS running Linux-based GNU systems with ELF format
-   using n32/64 abi.
+/* Definitions for 64-bit RISC-V GNU/Linux systems with ELF format.
    Copyright 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2010, 2011
    Free Software Foundation, Inc.
 
Index: src/external/gpl3/gcc/dist/gcc/config/riscv/opcode-riscv.h
diff -u src/external/gpl3/gcc/dist/gcc/config/riscv/opcode-riscv.h:1.1 src/external/gpl3/gcc/dist/gcc/config/riscv/opcode-riscv.h:1.2
--- src/external/gpl3/gcc/dist/gcc/config/riscv/opcode-riscv.h:1.1	Fri Sep 19 17:20:29 2014
+++ src/external/gpl3/gcc/dist/gcc/config/riscv/opcode-riscv.h	Fri Mar 27 01:51:34 2015
@@ -32,7 +32,7 @@ Software Foundation, 51 Franklin Street 
 #define EXTRACT_SBTYPE_IMM(x) \
   ((RV_X(x, 8, 4) << 1) | (RV_X(x, 25, 6) << 5) | (RV_X(x, 7, 1) << 11) | (RV_IMM_SIGN(x) << 12))
 #define EXTRACT_UTYPE_IMM(x) \
-  (RV_X(x, 12, 20) | (RV_IMM_SIGN(x) << 20))
+  ((RV_X(x, 12, 20) << 20) | (RV_IMM_SIGN(x) << 32))
 #define EXTRACT_UJTYPE_IMM(x) \
   ((RV_X(x, 21, 10) << 1) | (RV_X(x, 20, 1) << 11) | (RV_X(x, 12, 8) << 12) | (RV_IMM_SIGN(x) << 20))
 
@@ -43,7 +43,7 @@ Software Foundation, 51 Franklin Street 
 #define ENCODE_SBTYPE_IMM(x) \
   ((RV_X(x, 1, 4) << 8) | (RV_X(x, 5, 6) << 25) | (RV_X(x, 11, 1) << 7) | (RV_X(x, 12, 1) << 31))
 #define ENCODE_UTYPE_IMM(x) \
-  (RV_X(x, 0, 20) << 12)
+  (RV_X(x, 12, 20) << 12)
 #define ENCODE_UJTYPE_IMM(x) \
   ((RV_X(x, 1, 10) << 21) | (RV_X(x, 11, 1) << 20) | (RV_X(x, 12, 8) << 12) | (RV_X(x, 20, 1) << 31))
 
@@ -71,7 +71,6 @@ Software Foundation, 51 Franklin Street 
 #define RISCV_CONST_HIGH_PART(VALUE) \
   (((VALUE) + (RISCV_IMM_REACH/2)) & ~(RISCV_IMM_REACH-1))
 #define RISCV_CONST_LOW_PART(VALUE) ((VALUE) - RISCV_CONST_HIGH_PART (VALUE))
-#define RISCV_LUI_HIGH_PART(VALUE) (RISCV_CONST_HIGH_PART(VALUE) >> RISCV_IMM_BITS)
 
 /* RV fields */
 
Index: src/external/gpl3/gcc/dist/gcc/config/riscv/peephole.md
diff -u src/external/gpl3/gcc/dist/gcc/config/riscv/peephole.md:1.1 src/external/gpl3/gcc/dist/gcc/config/riscv/peephole.md:1.2
--- src/external/gpl3/gcc/dist/gcc/config/riscv/peephole.md:1.1	Fri Sep 19 17:20:29 2014
+++ src/external/gpl3/gcc/dist/gcc/config/riscv/peephole.md	Fri Mar 27 01:51:34 2015
@@ -10,7 +10,8 @@
 	   (match_operand:DI 2 "arith_operand")]))
    (set (match_operand:SI 3 "register_operand")
         (truncate:SI (match_dup 0)))]
-  "TARGET_64BIT && (REGNO (operands[0]) == REGNO (operands[3]) || peep2_reg_dead_p (2, operands[0]))"
+  "TARGET_64BIT && (REGNO (operands[0]) == REGNO (operands[3]) || peep2_reg_dead_p (2, operands[0]))
+   && (GET_CODE (operands[4]) != ASHIFT || (CONST_INT_P (operands[2]) && INTVAL (operands[2]) < 32))"
   [(set (match_dup 3)
           (truncate:SI
 	     (match_op_dup:DI 4 
@@ -42,37 +43,7 @@
 	(match_op_dup:SI 4 [(match_dup 1) (match_dup 2)]))])
 
 ;; Simplify PIC loads to static variables.
-(define_peephole2
-  [(set (match_operand:P 0 "register_operand")
-        (match_operand:P 1 "absolute_symbolic_operand"))
-   (set (match_operand:ANYI 2 "register_operand")
-	(mem:ANYI (match_dup 0)))]
-  "(flag_pic && SYMBOL_REF_LOCAL_P (operands[1])) && (REGNO (operands[0]) == REGNO (operands[2]) || peep2_reg_dead_p (2, operands[0]))"
-  [(set (match_dup 2) (mem:ANYI (match_dup 1)))])
-(define_peephole2
-  [(set (match_operand:P 0 "register_operand")
-        (match_operand:P 1 "absolute_symbolic_operand"))
-   (set (match_operand:ANYF 2 "register_operand")
-	(mem:ANYF (match_dup 0)))]
-  "(flag_pic && SYMBOL_REF_LOCAL_P (operands[1])) && peep2_reg_dead_p (2, operands[0])"
-  [(set (match_dup 2) (mem:ANYF (match_dup 1)))
-   (clobber (match_dup 0))])
-(define_peephole2
-  [(set (match_operand:DI 0 "register_operand")
-        (match_operand:DI 1 "absolute_symbolic_operand"))
-   (set (mem:ANYIF (match_dup 0))
-	(match_operand:ANYIF 2 "reg_or_0_operand"))]
-  "TARGET_64BIT && (flag_pic && SYMBOL_REF_LOCAL_P (operands[1])) && peep2_reg_dead_p (2, operands[0])"
-  [(set (mem:ANYIF (match_dup 1)) (match_dup 2))
-   (clobber (match_dup 0))])
-(define_peephole2
-  [(set (match_operand:SI 0 "register_operand")
-        (match_operand:SI 1 "absolute_symbolic_operand"))
-   (set (mem:ANYIF (match_dup 0))
-	(match_operand:ANYIF 2 "register_operand"))]
-  "!TARGET_64BIT && (flag_pic && SYMBOL_REF_LOCAL_P (operands[1])) && peep2_reg_dead_p (2, operands[0])"
-  [(set (mem:ANYIF (match_dup 1)) (match_dup 2))
-   (clobber (match_dup 0))])
+;; These will go away once we figure out how to emit auipc discretely.
 (define_insn "*local_pic_load<mode>"
   [(set (match_operand:ANYI 0 "register_operand" "=r")
         (mem:ANYI (match_operand 1 "absolute_symbolic_operand" "")))]
@@ -83,7 +54,14 @@
   [(set (match_operand:ANYF 0 "register_operand" "=f")
         (mem:ANYF (match_operand 1 "absolute_symbolic_operand" "")))
    (clobber (match_scratch:DI 2 "=&r"))]
-  "flag_pic && SYMBOL_REF_LOCAL_P (operands[1])"
+  "TARGET_HARD_FLOAT && TARGET_64BIT && flag_pic && SYMBOL_REF_LOCAL_P (operands[1])"
+  "<load>\t%0,%1,%2"
+  [(set (attr "length") (const_int 8))])
+(define_insn "*local_pic_load<mode>"
+  [(set (match_operand:ANYF 0 "register_operand" "=f")
+        (mem:ANYF (match_operand 1 "absolute_symbolic_operand" "")))
+   (clobber (match_scratch:SI 2 "=&r"))]
+  "TARGET_HARD_FLOAT && !TARGET_64BIT && flag_pic && SYMBOL_REF_LOCAL_P (operands[1])"
   "<load>\t%0,%1,%2"
   [(set (attr "length") (const_int 8))])
 (define_insn "*local_pic_loadu<mode>"
@@ -110,13 +88,13 @@
   [(set (mem:ANYF (match_operand 0 "absolute_symbolic_operand" ""))
 	(match_operand:ANYF 1 "register_operand" "f"))
    (clobber (match_scratch:DI 2 "=&r"))]
-  "TARGET_64BIT && (flag_pic && SYMBOL_REF_LOCAL_P (operands[0]))"
+  "TARGET_HARD_FLOAT && TARGET_64BIT && (flag_pic && SYMBOL_REF_LOCAL_P (operands[0]))"
   "<store>\t%1,%0,%2"
   [(set (attr "length") (const_int 8))])
 (define_insn "*local_pic_storesi<mode>"
   [(set (mem:ANYF (match_operand 0 "absolute_symbolic_operand" ""))
 	(match_operand:ANYF 1 "register_operand" "f"))
    (clobber (match_scratch:SI 2 "=&r"))]
-  "!TARGET_64BIT && (flag_pic && SYMBOL_REF_LOCAL_P (operands[0]))"
+  "TARGET_HARD_FLOAT && !TARGET_64BIT && (flag_pic && SYMBOL_REF_LOCAL_P (operands[0]))"
   "<store>\t%1,%0,%2"
   [(set (attr "length") (const_int 8))])
Index: src/external/gpl3/gcc/dist/gcc/config/riscv/riscv-opc.h
diff -u src/external/gpl3/gcc/dist/gcc/config/riscv/riscv-opc.h:1.1 src/external/gpl3/gcc/dist/gcc/config/riscv/riscv-opc.h:1.2
--- src/external/gpl3/gcc/dist/gcc/config/riscv/riscv-opc.h:1.1	Fri Sep 19 17:20:29 2014
+++ src/external/gpl3/gcc/dist/gcc/config/riscv/riscv-opc.h	Fri Mar 27 01:51:34 2015
@@ -297,6 +297,8 @@
 #define MASK_CUSTOM2_RD_RS1  0x707f
 #define MATCH_FCLASS_S 0xe0001053
 #define MASK_FCLASS_S  0xfff0707f
+#define MATCH_SFENCE_VM 0x10100073
+#define MASK_SFENCE_VM  0xfff07fff
 #define MATCH_REM 0x2006033
 #define MASK_REM  0xfe00707f
 #define MATCH_FCLASS_D 0xe2001053
@@ -465,6 +467,8 @@
 #define MASK_AMOAND_W  0xf800707f
 #define MATCH_CUSTOM2_RD 0x405b
 #define MASK_CUSTOM2_RD  0x707f
+#define MATCH_MRTS 0x30500073
+#define MASK_MRTS  0xffffffff
 #define MATCH_FCVT_WU_D 0xc2100053
 #define MASK_FCVT_WU_D  0xfff0007f
 #define MATCH_AMOXOR_W 0x2000202f
@@ -524,7 +528,7 @@
 #define MATCH_VXCPTRESTORE 0x200302b
 #define MASK_VXCPTRESTORE  0xfff07fff
 #define MATCH_VXCPTHOLD 0x800302b
-#define MASK_VXCPTHOLD  0xffffffff
+#define MASK_VXCPTHOLD  0xfff07fff
 #define MATCH_SLTIU 0x3013
 #define MASK_SLTIU  0x707f
 #define MATCH_VFLSEGSTD 0x1600305b
@@ -539,7 +543,7 @@
 #define MASK_FMADD_D  0x600007f
 #define MATCH_FMADD_H 0x4000043
 #define MASK_FMADD_H  0x600007f
-#define MATCH_SRET 0x80000073
+#define MATCH_SRET 0x10000073
 #define MASK_SRET  0xffffffff
 #define MATCH_VSSEGW 0x400207b
 #define MASK_VSSEGW  0x1ff0707f
@@ -708,29 +712,10 @@
 #define CSR_FFLAGS 0x1
 #define CSR_FRM 0x2
 #define CSR_FCSR 0x3
-#define CSR_STATS 0xc0
-#define CSR_SUP0 0x500
-#define CSR_SUP1 0x501
-#define CSR_EPC 0x502
-#define CSR_BADVADDR 0x503
-#define CSR_PTBR 0x504
-#define CSR_ASID 0x505
-#define CSR_COUNT 0x506
-#define CSR_COMPARE 0x507
-#define CSR_EVEC 0x508
-#define CSR_CAUSE 0x509
-#define CSR_STATUS 0x50a
-#define CSR_HARTID 0x50b
-#define CSR_IMPL 0x50c
-#define CSR_FATC 0x50d
-#define CSR_SEND_IPI 0x50e
-#define CSR_CLEAR_IPI 0x50f
-#define CSR_RESET 0x51d
-#define CSR_TOHOST 0x51e
-#define CSR_FROMHOST 0x51f
 #define CSR_CYCLE 0xc00
 #define CSR_TIME 0xc01
 #define CSR_INSTRET 0xc02
+#define CSR_STATS 0xc0
 #define CSR_UARCH0 0xcc0
 #define CSR_UARCH1 0xcc1
 #define CSR_UARCH2 0xcc2
@@ -747,22 +732,43 @@
 #define CSR_UARCH13 0xccd
 #define CSR_UARCH14 0xcce
 #define CSR_UARCH15 0xccf
-#define CSR_COUNTH 0x586
+#define CSR_SSTATUS 0x100
+#define CSR_STVEC 0x101
+#define CSR_STIMECMP 0x121
+#define CSR_SSCRATCH 0x140
+#define CSR_SEPC 0x141
+#define CSR_SPTBR 0x188
+#define CSR_SASID 0x189
+#define CSR_SCYCLE 0x900
+#define CSR_STIME 0x901
+#define CSR_SINSTRET 0x902
+#define CSR_SCAUSE 0xd40
+#define CSR_SBADADDR 0xd41
+#define CSR_MSTATUS 0x300
+#define CSR_MSCRATCH 0x340
+#define CSR_MEPC 0x341
+#define CSR_MCAUSE 0x342
+#define CSR_MBADADDR 0x343
+#define CSR_RESET 0x780
+#define CSR_TOHOST 0x781
+#define CSR_FROMHOST 0x782
+#define CSR_SEND_IPI 0x783
+#define CSR_HARTID 0xfc0
 #define CSR_CYCLEH 0xc80
 #define CSR_TIMEH 0xc81
 #define CSR_INSTRETH 0xc82
+#define CSR_SCYCLEH 0x980
+#define CSR_STIMEH 0x981
+#define CSR_SINSTRETH 0x982
 #define CAUSE_MISALIGNED_FETCH 0x0
 #define CAUSE_FAULT_FETCH 0x1
 #define CAUSE_ILLEGAL_INSTRUCTION 0x2
-#define CAUSE_PRIVILEGED_INSTRUCTION 0x3
-#define CAUSE_FP_DISABLED 0x4
-#define CAUSE_SYSCALL 0x6
-#define CAUSE_BREAKPOINT 0x7
-#define CAUSE_MISALIGNED_LOAD 0x8
-#define CAUSE_MISALIGNED_STORE 0x9
-#define CAUSE_FAULT_LOAD 0xa
-#define CAUSE_FAULT_STORE 0xb
-#define CAUSE_ACCELERATOR_DISABLED 0xc
+#define CAUSE_MISALIGNED_LOAD 0x4
+#define CAUSE_FAULT_LOAD 0x5
+#define CAUSE_MISALIGNED_STORE 0x6
+#define CAUSE_FAULT_STORE 0x7
+#define CAUSE_ECALL 0x8
+#define CAUSE_BREAKPOINT 0x9
 #endif
 #ifdef DECLARE_INSN
 DECLARE_INSN(custom3_rd_rs1_rs2, MATCH_CUSTOM3_RD_RS1_RS2, MASK_CUSTOM3_RD_RS1_RS2)
@@ -913,6 +919,7 @@ DECLARE_INSN(jalr, MATCH_JALR, MASK_JALR
 DECLARE_INSN(blt, MATCH_BLT, MASK_BLT)
 DECLARE_INSN(custom2_rd_rs1, MATCH_CUSTOM2_RD_RS1, MASK_CUSTOM2_RD_RS1)
 DECLARE_INSN(fclass_s, MATCH_FCLASS_S, MASK_FCLASS_S)
+DECLARE_INSN(sfence_vm, MATCH_SFENCE_VM, MASK_SFENCE_VM)
 DECLARE_INSN(rem, MATCH_REM, MASK_REM)
 DECLARE_INSN(fclass_d, MATCH_FCLASS_D, MASK_FCLASS_D)
 DECLARE_INSN(fmul_s, MATCH_FMUL_S, MASK_FMUL_S)
@@ -997,6 +1004,7 @@ DECLARE_INSN(flt_s, MATCH_FLT_S, MASK_FL
 DECLARE_INSN(addiw, MATCH_ADDIW, MASK_ADDIW)
 DECLARE_INSN(amoand_w, MATCH_AMOAND_W, MASK_AMOAND_W)
 DECLARE_INSN(custom2_rd, MATCH_CUSTOM2_RD, MASK_CUSTOM2_RD)
+DECLARE_INSN(mrts, MATCH_MRTS, MASK_MRTS)
 DECLARE_INSN(fcvt_wu_d, MATCH_FCVT_WU_D, MASK_FCVT_WU_D)
 DECLARE_INSN(amoxor_w, MATCH_AMOXOR_W, MASK_AMOXOR_W)
 DECLARE_INSN(fcvt_d_l, MATCH_FCVT_D_L, MASK_FCVT_D_L)
@@ -1122,29 +1130,10 @@ DECLARE_INSN(c_j, MATCH_C_J, MASK_C_J)
 DECLARE_CSR(fflags, CSR_FFLAGS)
 DECLARE_CSR(frm, CSR_FRM)
 DECLARE_CSR(fcsr, CSR_FCSR)
-DECLARE_CSR(stats, CSR_STATS)
-DECLARE_CSR(sup0, CSR_SUP0)
-DECLARE_CSR(sup1, CSR_SUP1)
-DECLARE_CSR(epc, CSR_EPC)
-DECLARE_CSR(badvaddr, CSR_BADVADDR)
-DECLARE_CSR(ptbr, CSR_PTBR)
-DECLARE_CSR(asid, CSR_ASID)
-DECLARE_CSR(count, CSR_COUNT)
-DECLARE_CSR(compare, CSR_COMPARE)
-DECLARE_CSR(evec, CSR_EVEC)
-DECLARE_CSR(cause, CSR_CAUSE)
-DECLARE_CSR(status, CSR_STATUS)
-DECLARE_CSR(hartid, CSR_HARTID)
-DECLARE_CSR(impl, CSR_IMPL)
-DECLARE_CSR(fatc, CSR_FATC)
-DECLARE_CSR(send_ipi, CSR_SEND_IPI)
-DECLARE_CSR(clear_ipi, CSR_CLEAR_IPI)
-DECLARE_CSR(reset, CSR_RESET)
-DECLARE_CSR(tohost, CSR_TOHOST)
-DECLARE_CSR(fromhost, CSR_FROMHOST)
 DECLARE_CSR(cycle, CSR_CYCLE)
 DECLARE_CSR(time, CSR_TIME)
 DECLARE_CSR(instret, CSR_INSTRET)
+DECLARE_CSR(stats, CSR_STATS)
 DECLARE_CSR(uarch0, CSR_UARCH0)
 DECLARE_CSR(uarch1, CSR_UARCH1)
 DECLARE_CSR(uarch2, CSR_UARCH2)
@@ -1161,38 +1150,43 @@ DECLARE_CSR(uarch12, CSR_UARCH12)
 DECLARE_CSR(uarch13, CSR_UARCH13)
 DECLARE_CSR(uarch14, CSR_UARCH14)
 DECLARE_CSR(uarch15, CSR_UARCH15)
-DECLARE_CSR(counth, CSR_COUNTH)
+DECLARE_CSR(sstatus, CSR_SSTATUS)
+DECLARE_CSR(stvec, CSR_STVEC)
+DECLARE_CSR(stimecmp, CSR_STIMECMP)
+DECLARE_CSR(sscratch, CSR_SSCRATCH)
+DECLARE_CSR(sepc, CSR_SEPC)
+DECLARE_CSR(sptbr, CSR_SPTBR)
+DECLARE_CSR(sasid, CSR_SASID)
+DECLARE_CSR(scycle, CSR_SCYCLE)
+DECLARE_CSR(stime, CSR_STIME)
+DECLARE_CSR(sinstret, CSR_SINSTRET)
+DECLARE_CSR(scause, CSR_SCAUSE)
+DECLARE_CSR(sbadaddr, CSR_SBADADDR)
+DECLARE_CSR(mstatus, CSR_MSTATUS)
+DECLARE_CSR(mscratch, CSR_MSCRATCH)
+DECLARE_CSR(mepc, CSR_MEPC)
+DECLARE_CSR(mcause, CSR_MCAUSE)
+DECLARE_CSR(mbadaddr, CSR_MBADADDR)
+DECLARE_CSR(reset, CSR_RESET)
+DECLARE_CSR(tohost, CSR_TOHOST)
+DECLARE_CSR(fromhost, CSR_FROMHOST)
+DECLARE_CSR(send_ipi, CSR_SEND_IPI)
+DECLARE_CSR(hartid, CSR_HARTID)
 DECLARE_CSR(cycleh, CSR_CYCLEH)
 DECLARE_CSR(timeh, CSR_TIMEH)
 DECLARE_CSR(instreth, CSR_INSTRETH)
+DECLARE_CSR(scycleh, CSR_SCYCLEH)
+DECLARE_CSR(stimeh, CSR_STIMEH)
+DECLARE_CSR(sinstreth, CSR_SINSTRETH)
 #endif
 #ifdef DECLARE_CAUSE
 DECLARE_CAUSE("fflags", CAUSE_FFLAGS)
 DECLARE_CAUSE("frm", CAUSE_FRM)
 DECLARE_CAUSE("fcsr", CAUSE_FCSR)
-DECLARE_CAUSE("stats", CAUSE_STATS)
-DECLARE_CAUSE("sup0", CAUSE_SUP0)
-DECLARE_CAUSE("sup1", CAUSE_SUP1)
-DECLARE_CAUSE("epc", CAUSE_EPC)
-DECLARE_CAUSE("badvaddr", CAUSE_BADVADDR)
-DECLARE_CAUSE("ptbr", CAUSE_PTBR)
-DECLARE_CAUSE("asid", CAUSE_ASID)
-DECLARE_CAUSE("count", CAUSE_COUNT)
-DECLARE_CAUSE("compare", CAUSE_COMPARE)
-DECLARE_CAUSE("evec", CAUSE_EVEC)
-DECLARE_CAUSE("cause", CAUSE_CAUSE)
-DECLARE_CAUSE("status", CAUSE_STATUS)
-DECLARE_CAUSE("hartid", CAUSE_HARTID)
-DECLARE_CAUSE("impl", CAUSE_IMPL)
-DECLARE_CAUSE("fatc", CAUSE_FATC)
-DECLARE_CAUSE("send_ipi", CAUSE_SEND_IPI)
-DECLARE_CAUSE("clear_ipi", CAUSE_CLEAR_IPI)
-DECLARE_CAUSE("reset", CAUSE_RESET)
-DECLARE_CAUSE("tohost", CAUSE_TOHOST)
-DECLARE_CAUSE("fromhost", CAUSE_FROMHOST)
 DECLARE_CAUSE("cycle", CAUSE_CYCLE)
 DECLARE_CAUSE("time", CAUSE_TIME)
 DECLARE_CAUSE("instret", CAUSE_INSTRET)
+DECLARE_CAUSE("stats", CAUSE_STATS)
 DECLARE_CAUSE("uarch0", CAUSE_UARCH0)
 DECLARE_CAUSE("uarch1", CAUSE_UARCH1)
 DECLARE_CAUSE("uarch2", CAUSE_UARCH2)
@@ -1209,8 +1203,32 @@ DECLARE_CAUSE("uarch12", CAUSE_UARCH12)
 DECLARE_CAUSE("uarch13", CAUSE_UARCH13)
 DECLARE_CAUSE("uarch14", CAUSE_UARCH14)
 DECLARE_CAUSE("uarch15", CAUSE_UARCH15)
-DECLARE_CAUSE("counth", CAUSE_COUNTH)
+DECLARE_CAUSE("sstatus", CAUSE_SSTATUS)
+DECLARE_CAUSE("stvec", CAUSE_STVEC)
+DECLARE_CAUSE("stimecmp", CAUSE_STIMECMP)
+DECLARE_CAUSE("sscratch", CAUSE_SSCRATCH)
+DECLARE_CAUSE("sepc", CAUSE_SEPC)
+DECLARE_CAUSE("sptbr", CAUSE_SPTBR)
+DECLARE_CAUSE("sasid", CAUSE_SASID)
+DECLARE_CAUSE("scycle", CAUSE_SCYCLE)
+DECLARE_CAUSE("stime", CAUSE_STIME)
+DECLARE_CAUSE("sinstret", CAUSE_SINSTRET)
+DECLARE_CAUSE("scause", CAUSE_SCAUSE)
+DECLARE_CAUSE("sbadaddr", CAUSE_SBADADDR)
+DECLARE_CAUSE("mstatus", CAUSE_MSTATUS)
+DECLARE_CAUSE("mscratch", CAUSE_MSCRATCH)
+DECLARE_CAUSE("mepc", CAUSE_MEPC)
+DECLARE_CAUSE("mcause", CAUSE_MCAUSE)
+DECLARE_CAUSE("mbadaddr", CAUSE_MBADADDR)
+DECLARE_CAUSE("reset", CAUSE_RESET)
+DECLARE_CAUSE("tohost", CAUSE_TOHOST)
+DECLARE_CAUSE("fromhost", CAUSE_FROMHOST)
+DECLARE_CAUSE("send_ipi", CAUSE_SEND_IPI)
+DECLARE_CAUSE("hartid", CAUSE_HARTID)
 DECLARE_CAUSE("cycleh", CAUSE_CYCLEH)
 DECLARE_CAUSE("timeh", CAUSE_TIMEH)
 DECLARE_CAUSE("instreth", CAUSE_INSTRETH)
+DECLARE_CAUSE("scycleh", CAUSE_SCYCLEH)
+DECLARE_CAUSE("stimeh", CAUSE_STIMEH)
+DECLARE_CAUSE("sinstreth", CAUSE_SINSTRETH)
 #endif
Index: src/external/gpl3/gcc/dist/gcc/config/riscv/riscv-protos.h
diff -u src/external/gpl3/gcc/dist/gcc/config/riscv/riscv-protos.h:1.1 src/external/gpl3/gcc/dist/gcc/config/riscv/riscv-protos.h:1.2
--- src/external/gpl3/gcc/dist/gcc/config/riscv/riscv-protos.h:1.1	Fri Sep 19 17:20:29 2014
+++ src/external/gpl3/gcc/dist/gcc/config/riscv/riscv-protos.h	Fri Mar 27 01:51:34 2015
@@ -27,9 +27,17 @@ enum riscv_symbol_type {
   SYMBOL_GOT_DISP,
   SYMBOL_TLS,
   SYMBOL_TLS_LE,
-  SYMBOL_TLS_IE
+  SYMBOL_TLS_IE,
+  SYMBOL_TLS_GD
 };
-#define NUM_SYMBOL_TYPES (SYMBOL_TLS_IE + 1)
+#define NUM_SYMBOL_TYPES (SYMBOL_TLS_GD + 1)
+
+enum riscv_code_model {
+  CM_MEDLOW,
+  CM_MEDANY,
+  CM_PIC
+};
+extern enum riscv_code_model riscv_cmodel;
 
 extern bool riscv_symbolic_constant_p (rtx, enum riscv_symbol_type *);
 extern int riscv_regno_mode_ok_for_base_p (int, enum machine_mode, bool);
@@ -85,6 +93,4 @@ extern unsigned int current_section_flag
 
 extern void riscv_expand_vector_init (rtx, rtx);
 
-extern bool riscv_size_ok_for_small_data_p (int size);
-
 #endif /* ! GCC_RISCV_PROTOS_H */
Index: src/external/gpl3/gcc/dist/gcc/config/riscv/riscv.c
diff -u src/external/gpl3/gcc/dist/gcc/config/riscv/riscv.c:1.1 src/external/gpl3/gcc/dist/gcc/config/riscv/riscv.c:1.2
--- src/external/gpl3/gcc/dist/gcc/config/riscv/riscv.c:1.1	Fri Sep 19 17:20:29 2014
+++ src/external/gpl3/gcc/dist/gcc/config/riscv/riscv.c	Fri Mar 27 01:51:34 2015
@@ -108,6 +108,8 @@ enum riscv_address_type {
   ADDRESS_SYMBOLIC
 };
 
+enum riscv_code_model riscv_cmodel = CM_MEDLOW;
+
 /* Macros to create an enumeration identifier for a function prototype.  */
 #define RISCV_FTYPE_NAME1(A, B) RISCV_##A##_FTYPE_##B
 #define RISCV_FTYPE_NAME2(A, B, C) RISCV_##A##_FTYPE_##B##_##C
@@ -231,35 +233,41 @@ struct riscv_integer_op {
 };
 
 /* The largest number of operations needed to load an integer constant.
-   The worst accepted case for 64-bit constants is LUI,ORI,SLL,ORI,SLL,ORI.
-   When the lowest bit is clear, we can try, but reject a sequence with
-   an extra SLL at the end.  */
+   The worst case is LUI, ADDI, SLLI, ADDI, SLLI, ADDI, SLLI, ADDI,
+   but we may attempt and reject even worse sequences.  */
 #define RISCV_MAX_INTEGER_OPS 32
 
 /* Costs of various operations on the different architectures.  */
 
-struct riscv_rtx_cost_data
+struct riscv_tune_info
 {
-  unsigned short fp_add;
-  unsigned short fp_mult_sf;
-  unsigned short fp_mult_df;
-  unsigned short fp_div_sf;
-  unsigned short fp_div_df;
-  unsigned short int_mult_si;
-  unsigned short int_mult_di;
-  unsigned short int_div_si;
-  unsigned short int_div_di;
+  unsigned short fp_add[2];
+  unsigned short fp_mul[2];
+  unsigned short fp_div[2];
+  unsigned short int_mul[2];
+  unsigned short int_div[2];
+  unsigned short issue_rate;
   unsigned short branch_cost;
-  unsigned short memory_latency;
+  unsigned short fp_to_int_cost;
+  unsigned short memory_cost;
 };
 
-/* Global variables for machine-dependent things.  */
+/* Information about one CPU we know about.  */
+struct riscv_cpu_info {
+  /* This CPU's canonical name.  */
+  const char *name;
+
+  /* The RISC-V ISA and extensions supported by this CPU.  */
+  const char *isa;
+
+  /* Tuning parameters for this CPU.  */
+  const struct riscv_tune_info *tune_info;
+};
 
-/* The processor that we should tune the code for.  */
-enum processor riscv_tune;
+/* Global variables for machine-dependent things.  */
 
-/* Which cost information to use.  */
-static const struct riscv_rtx_cost_data *riscv_cost;
+/* Which tuning parameters to use.  */
+static const struct riscv_tune_info *tune_info;
 
 /* Index [M][R] is true if register R is allowed to hold a value of mode M.  */
 bool riscv_hard_regno_mode_ok[(int) MAX_MACHINE_MODE][FIRST_PSEUDO_REGISTER];
@@ -275,13 +283,13 @@ const char *riscv_hi_relocs[NUM_SYMBOL_T
 /* Index R is the smallest register class that contains register R.  */
 const enum reg_class riscv_regno_to_class[FIRST_PSEUDO_REGISTER] = {
   GR_REGS,	GR_REGS,	GR_REGS,	GR_REGS,
-  GR_REGS,	GR_REGS,	GR_REGS,	GR_REGS,
+  GR_REGS,	T_REGS,		T_REGS,		T_REGS,
   GR_REGS,	GR_REGS,	GR_REGS,	GR_REGS,
   GR_REGS,	GR_REGS,	GR_REGS,	GR_REGS,
   GR_REGS,	GR_REGS, 	GR_REGS,	GR_REGS,
   GR_REGS,	GR_REGS,	GR_REGS,	GR_REGS,
-  GR_REGS,	GR_REGS,	T_REGS,		T_REGS,
-  T_REGS,	T_REGS,		T_REGS,		GR_REGS,
+  GR_REGS,	GR_REGS,	GR_REGS,	GR_REGS,
+  T_REGS,	T_REGS,		T_REGS,		T_REGS,
   FP_REGS,	FP_REGS,	FP_REGS,	FP_REGS,
   FP_REGS,	FP_REGS,	FP_REGS,	FP_REGS,
   FP_REGS,	FP_REGS,	FP_REGS,	FP_REGS,
@@ -293,89 +301,51 @@ const enum reg_class riscv_regno_to_clas
   FRAME_REGS,	FRAME_REGS,
 };
 
-/* A table describing all the processors GCC knows about.  Names are
-   matched in the order listed.  The first mention of an ISA level is
-   taken as the canonical name for that ISA.
-
-   To ease comparison, please keep this table in the same order
-   as GAS's riscv_cpu_info_table.  Please also make sure that
-   MIPS_ISA_LEVEL_SPEC and MIPS_ARCH_FLOAT_SPEC handle all -march
-   options correctly.  */
-static const struct riscv_cpu_info riscv_cpu_info_table[] = {
-  /* Entries for generic ISAs.  */
-  { "rocket", PROCESSOR_ROCKET, 0 },
+/* Costs to use when optimizing for size.  */
+static const struct riscv_tune_info rocket_tune_info = {
+  {COSTS_N_INSNS (4), COSTS_N_INSNS (5)},	/* fp_add */
+  {COSTS_N_INSNS (4), COSTS_N_INSNS (5)},	/* fp_mul */
+  {COSTS_N_INSNS (20), COSTS_N_INSNS (20)},	/* fp_div */
+  {COSTS_N_INSNS (4), COSTS_N_INSNS (4)},	/* int_mul */
+  {COSTS_N_INSNS (6), COSTS_N_INSNS (6)},	/* int_div */
+  1,						/* issue_rate */
+  3,						/* branch_cost */
+  COSTS_N_INSNS (2),				/* fp_to_int_cost */
+  5						/* memory_cost */
 };
 
-/* Default costs.  If these are used for a processor we should look
-   up the actual costs.  */
-#define DEFAULT_COSTS COSTS_N_INSNS (8),  /* fp_add */       \
-                      COSTS_N_INSNS (8),  /* fp_mult_sf */   \
-                      COSTS_N_INSNS (8),  /* fp_mult_df */   \
-                      COSTS_N_INSNS (20), /* fp_div_sf */    \
-                      COSTS_N_INSNS (20), /* fp_div_df */    \
-                      COSTS_N_INSNS (4),  /* int_mult_si */  \
-                      COSTS_N_INSNS (4),  /* int_mult_di */  \
-                      COSTS_N_INSNS (6),  /* int_div_si */   \
-                      COSTS_N_INSNS (6),  /* int_div_di */   \
-                                       2, /* branch_cost */  \
-                                       7  /* memory_latency */
-
-/* Floating-point costs for processors without an FPU.  Just assume that
-   all floating-point libcalls are very expensive.  */
-#define SOFT_FP_COSTS COSTS_N_INSNS (256), /* fp_add */       \
-                      COSTS_N_INSNS (256), /* fp_mult_sf */   \
-                      COSTS_N_INSNS (256), /* fp_mult_df */   \
-                      COSTS_N_INSNS (256), /* fp_div_sf */    \
-                      COSTS_N_INSNS (256)  /* fp_div_df */
-
 /* Costs to use when optimizing for size.  */
-static const struct riscv_rtx_cost_data riscv_rtx_cost_optimize_size = {
-  COSTS_N_INSNS (1),            /* fp_add */
-  COSTS_N_INSNS (1),            /* fp_mult_sf */
-  COSTS_N_INSNS (1),            /* fp_mult_df */
-  COSTS_N_INSNS (1),            /* fp_div_sf */
-  COSTS_N_INSNS (1),            /* fp_div_df */
-  COSTS_N_INSNS (1),            /* int_mult_si */
-  COSTS_N_INSNS (1),            /* int_mult_di */
-  COSTS_N_INSNS (1),            /* int_div_si */
-  COSTS_N_INSNS (1),            /* int_div_di */
-		   1,           /* branch_cost */
-		   1            /* memory_latency */
+static const struct riscv_tune_info optimize_size_tune_info = {
+  {COSTS_N_INSNS (1), COSTS_N_INSNS (1)},	/* fp_add */
+  {COSTS_N_INSNS (1), COSTS_N_INSNS (1)},	/* fp_mul */
+  {COSTS_N_INSNS (1), COSTS_N_INSNS (1)},	/* fp_div */
+  {COSTS_N_INSNS (1), COSTS_N_INSNS (1)},	/* int_mul */
+  {COSTS_N_INSNS (1), COSTS_N_INSNS (1)},	/* int_div */
+  1,						/* issue_rate */
+  1,						/* branch_cost */
+  COSTS_N_INSNS (1),				/* fp_to_int_cost */
+  1						/* memory_cost */
 };
 
-/* Costs to use when optimizing for speed, indexed by processor.  */
-static const struct riscv_rtx_cost_data
-  riscv_rtx_cost_data[NUM_PROCESSOR_VALUES] = {
-  { /* Rocket */ DEFAULT_COSTS},
+/* A table describing all the processors GCC knows about.  */
+static const struct riscv_cpu_info riscv_cpu_info_table[] = {
+  /* Entries for generic ISAs.  */
+  { "rocket", "IMAFD", &rocket_tune_info },
 };
 
-/* Predicates to test for presence of "near" and "far"/"long_call"
-   attributes on the given TYPE.  */
-
-static bool
-riscv_near_type_p (const_tree type)
-{
-  return lookup_attribute ("near", TYPE_ATTRIBUTES (type)) != NULL;
-}
+/* Return the riscv_cpu_info entry for the given name string.  */
 
-static bool
-riscv_far_type_p (const_tree type)
+static const struct riscv_cpu_info *
+riscv_parse_cpu (const char *cpu_string)
 {
-  return (lookup_attribute ("long_call", TYPE_ATTRIBUTES (type)) != NULL
-	  || lookup_attribute ("far", TYPE_ATTRIBUTES (type)) != NULL);
-}
+  unsigned int i;
 
-/* Implement TARGET_COMP_TYPE_ATTRIBUTES.  */
+  for (i = 0; i < ARRAY_SIZE (riscv_cpu_info_table); i++)
+    if (strcmp (riscv_cpu_info_table[i].name, cpu_string) == 0)
+      return riscv_cpu_info_table + i;
 
-static int
-riscv_comp_type_attributes (const_tree type1, const_tree type2)
-{
-  /* Disallow mixed near/far attributes.  */
-  if (riscv_far_type_p (type1) && riscv_near_type_p (type2))
-    return 0;
-  if (riscv_near_type_p (type1) && riscv_far_type_p (type2))
-    return 0;
-  return 1;
+  error ("unknown cpu `%s'", cpu_string);
+  return riscv_cpu_info_table;
 }
 
 /* Fill CODES with a sequence of rtl operations to load VALUE.
@@ -419,8 +389,10 @@ riscv_build_integer_1 (struct riscv_inte
   /* Eliminate trailing zeros and end with SLLI */
   if (cost > 2 && (value & 1) == 0)
     {
-      int shift = __builtin_ctzl(value);
-      alt_cost = 1 + riscv_build_integer_1 (alt_codes, value >> shift, mode);
+      int shift = 0;
+      while ((value & 1) == 0)
+	shift++, value >>= 1;
+      alt_cost = 1 + riscv_build_integer_1 (alt_codes, value, mode);
       alt_codes[alt_cost-1].code = ASHIFT;
       alt_codes[alt_cost-1].value = shift;
       if (alt_cost < cost)
@@ -441,11 +413,12 @@ riscv_build_integer (struct riscv_intege
   if (value > 0 && cost > 2)
     {
       struct riscv_integer_op alt_codes[RISCV_MAX_INTEGER_OPS];
-      int alt_cost, shift;
+      int alt_cost, shift = 0;
       HOST_WIDE_INT shifted_val;
 
       /* Try filling trailing bits with 1s */
-      shift = __builtin_clzl(value);
+      while ((value << shift) >= 0)
+	shift++;
       shifted_val = (value << shift) | ((((HOST_WIDE_INT) 1) << shift) - 1);
       alt_cost = 1 + riscv_build_integer_1 (alt_codes, shifted_val, mode);
       alt_codes[alt_cost-1].code = LSHIFTRT;
@@ -586,12 +559,10 @@ riscv_symbolic_constant_p (rtx x, enum r
   switch (*symbol_type)
     {
     case SYMBOL_ABSOLUTE:
+    case SYMBOL_TLS_LE:
       return (int32_t) INTVAL (offset) == INTVAL (offset);
 
-    case SYMBOL_TLS:
-    case SYMBOL_TLS_LE:
-    case SYMBOL_TLS_IE:
-    case SYMBOL_GOT_DISP:
+    default:
       return false;
     }
   gcc_unreachable ();
@@ -606,7 +577,6 @@ static int riscv_symbol_insns (enum risc
     case SYMBOL_TLS: return 0; /* Depends on the TLS model. */
     case SYMBOL_ABSOLUTE: return 2; /* LUI + the reference itself */
     case SYMBOL_TLS_LE: return 3; /* LUI + ADD TP + the reference itself */
-    case SYMBOL_TLS_IE: return 4; /* LUI + LD + ADD TP + the reference itself */
     case SYMBOL_GOT_DISP: return 3; /* AUIPC + LD GOT + the reference itself */
     default: gcc_unreachable();
   }
@@ -660,6 +630,10 @@ riscv_cannot_force_const_mem (enum machi
       /* The same optimization as for CONST_INT.  */
       if (SMALL_INT (offset) && riscv_symbol_insns (type) > 0)
 	return true;
+
+      /* It's not worth creating additional dynamic relocations.  */
+      if (flag_pic)
+	return true;
     }
 
   /* TLS symbols must be computed by riscv_legitimize_move.  */
@@ -798,20 +772,6 @@ riscv_classify_address (struct riscv_add
       info->type = ADDRESS_CONST_INT;
       return SMALL_INT (x);
 
-    case CONST:
-    case LABEL_REF:
-    case SYMBOL_REF:
-      if (riscv_symbolic_constant_p (x, &info->symbol_type)
-	  && riscv_symbol_insns (info->symbol_type) > 0
-	  && !riscv_hi_relocs[info->symbol_type]
-	  && riscv_lo_relocs[info->symbol_type])
-	{
-	  info->type = ADDRESS_LO_SUM;
-	  info->reg = gen_rtx_REG (Pmode, GP_REGNUM);
-	  info->offset = x;
-	  return true;
-	}
-
     default:
       return false;
     }
@@ -847,8 +807,8 @@ riscv_address_insns (rtx x, enum machine
   if (mode != BLKmode && might_split_p)
     n += (GET_MODE_SIZE (mode) + UNITS_PER_WORD - 1) / UNITS_PER_WORD;
 
-  if (addr.type == ADDRESS_SYMBOLIC)
-    n *= riscv_symbol_insns (addr.symbol_type);
+  if (addr.type == ADDRESS_LO_SUM)
+    n += riscv_symbol_insns (addr.symbol_type) - 1;
 
   return n;
 }
@@ -1075,22 +1035,6 @@ static rtx riscv_got_load_tls_ie(rtx des
   return (Pmode == DImode ? gen_got_load_tls_iedi(dest, sym) : gen_got_load_tls_iesi(dest, sym));
 }
 
-static rtx riscv_got_load_tls_ie_hi(rtx dest, rtx sym)
-{
-  return (Pmode == DImode ? gen_got_load_tls_ie_hidi(dest, sym) : gen_got_load_tls_ie_hisi(dest, sym));
-}
-
-static rtx riscv_got_load_tls_ie_lo(rtx dest, rtx base, rtx sym)
-{
-  return (Pmode == DImode ? gen_got_load_tls_ie_lodi(dest, base, sym) : gen_got_load_tls_ie_losi(dest, base, sym));
-}
-
-static rtx riscv_tls_add_tp_ie(rtx dest, rtx base, rtx sym)
-{
-  rtx tp = gen_rtx_REG (Pmode, THREAD_POINTER_REGNUM);
-  return (Pmode == DImode ? gen_tls_add_tp_iedi(dest, base, tp, sym) : gen_tls_add_tp_iesi(dest, base, tp, sym));
-}
-
 static rtx riscv_tls_add_tp_le(rtx dest, rtx base, rtx sym)
 {
   rtx tp = gen_rtx_REG (Pmode, THREAD_POINTER_REGNUM);
@@ -1167,23 +1111,21 @@ static GTY(()) rtx riscv_tls_symbol;
 
 /* Return an instruction sequence that calls __tls_get_addr.  SYM is
    the TLS symbol we are referencing and TYPE is the symbol type to use
-   (either global dynamic or local dynamic).  V0 is an RTX for the
+   (either global dynamic or local dynamic).  RESULT is an RTX for the
    return value location.  */
 
 static rtx
-riscv_call_tls_get_addr (rtx sym, rtx v0)
+riscv_call_tls_get_addr (rtx sym, rtx result)
 {
-  rtx insn, a0;
-
-  a0 = gen_rtx_REG (Pmode, GP_ARG_FIRST);
+  rtx insn, a0 = gen_rtx_REG (Pmode, GP_ARG_FIRST);
 
   if (!riscv_tls_symbol)
     riscv_tls_symbol = init_one_libfunc ("__tls_get_addr");
 
   start_sequence ();
   
-  emit_insn (riscv_got_load_tls_gd(a0, sym));
-  insn = riscv_expand_call (false, v0, riscv_tls_symbol, const0_rtx);
+  emit_insn (riscv_got_load_tls_gd (a0, sym));
+  insn = riscv_expand_call (false, result, riscv_tls_symbol, const0_rtx);
   RTL_CONST_CALL_P (insn) = 1;
   use_reg (&CALL_INSN_FUNCTION_USAGE (insn), a0);
   insn = get_insns ();
@@ -1200,42 +1142,32 @@ riscv_call_tls_get_addr (rtx sym, rtx v0
 static rtx
 riscv_legitimize_tls_address (rtx loc)
 {
-  rtx dest, insn, v0, tp, tmp1;
+  rtx dest, insn, tp, tmp1;
+  enum tls_model model = SYMBOL_REF_TLS_MODEL (loc);
 
-  switch (SYMBOL_REF_TLS_MODEL (loc))
+  /* Since we support TLS copy relocs, non-PIC TLS accesses may all use LE.  */
+  if (!flag_pic)
+    model = TLS_MODEL_LOCAL_EXEC;
+
+  switch (model)
     {
     case TLS_MODEL_LOCAL_DYNAMIC:
       /* Rely on section anchors for the optimization that LDM TLS
 	 provides.  The anchor's address is loaded with GD TLS. */
     case TLS_MODEL_GLOBAL_DYNAMIC:
-      v0 = gen_rtx_REG (Pmode, GP_RETURN);
-      insn = riscv_call_tls_get_addr (loc, v0);
+      tmp1 = gen_rtx_REG (Pmode, GP_RETURN);
+      insn = riscv_call_tls_get_addr (loc, tmp1);
       dest = gen_reg_rtx (Pmode);
-      emit_libcall_block (insn, dest, v0, loc);
+      emit_libcall_block (insn, dest, tmp1, loc);
       break;
 
     case TLS_MODEL_INITIAL_EXEC:
-      if (flag_pic)
-	{
-	  /* la.tls.ie; tp-relative add */
-	  tp = gen_rtx_REG (Pmode, THREAD_POINTER_REGNUM);
-	  tmp1 = gen_reg_rtx (Pmode);
-	  emit_insn (riscv_got_load_tls_ie (tmp1, loc));
-	  dest = gen_reg_rtx (Pmode);
-	  emit_insn (gen_add3_insn (dest, tmp1, tp));
-	}
-      else
-	{
-	  /* lui %tls_ie_hi; ld %tls_le_lo; tp-relative add */
-	  tmp1 = gen_reg_rtx (Pmode);
-	  emit_insn (riscv_got_load_tls_ie_hi (tmp1, loc));
-	  dest = gen_reg_rtx (Pmode);
-	  emit_insn (riscv_got_load_tls_ie_lo (dest, tmp1, loc));
-	  tmp1 = gen_reg_rtx (Pmode);
-	  emit_insn (riscv_tls_add_tp_ie (tmp1, dest, loc));
-	  dest = gen_rtx_LO_SUM (Pmode, tmp1,
-				 riscv_unspec_address (loc, SYMBOL_TLS_IE));
-	}
+      /* la.tls.ie; tp-relative add */
+      tp = gen_rtx_REG (Pmode, THREAD_POINTER_REGNUM);
+      tmp1 = gen_reg_rtx (Pmode);
+      emit_insn (riscv_got_load_tls_ie (tmp1, loc));
+      dest = gen_reg_rtx (Pmode);
+      emit_insn (gen_add3_insn (dest, tmp1, tp));
       break;
 
     case TLS_MODEL_LOCAL_EXEC:
@@ -1408,10 +1340,6 @@ riscv_legitimize_move (enum machine_mode
   return false;
 }
 
-/* The cost of loading values from the constant pool.  It should be
-   larger than the cost of any constant we want to synthesize inline.  */
-#define CONSTANT_POOL_COST COSTS_N_INSNS (8)
-
 /* Return true if there is an instruction that implements CODE and accepts
    X as an immediate operand. */
 
@@ -1455,36 +1383,16 @@ riscv_immediate_operand_p (int code, HOS
 }
 
 /* Return the cost of binary operation X, given that the instruction
-   sequence for a word-sized or smaller operation has cost SINGLE_COST
-   and that the sequence of a double-word operation has cost DOUBLE_COST.
-   If SPEED is true, optimize for speed otherwise optimize for size.  */
+   sequence for a word-sized or smaller operation takes SIGNLE_INSNS
+   instructions and that the sequence of a double-word operation takes
+   DOUBLE_INSNS instructions.  */
 
 static int
-riscv_binary_cost (rtx x, int single_cost, int double_cost, bool speed)
+riscv_binary_cost (rtx x, int single_insns, int double_insns)
 {
-  int cost = single_cost;
   if (GET_MODE_SIZE (GET_MODE (x)) == UNITS_PER_WORD * 2)
-    cost = double_cost;
-
-  return (cost
-	  + set_src_cost (XEXP (x, 0), speed)
-	  + rtx_cost (XEXP (x, 1), GET_CODE (x), 1, speed));
-}
-
-/* Return the cost of floating-point multiplications of mode MODE.  */
-
-static int
-riscv_fp_mult_cost (enum machine_mode mode)
-{
-  return mode == DFmode ? riscv_cost->fp_mult_df : riscv_cost->fp_mult_sf;
-}
-
-/* Return the cost of floating-point divisions of mode MODE.  */
-
-static int
-riscv_fp_div_cost (enum machine_mode mode)
-{
-  return mode == DFmode ? riscv_cost->fp_div_df : riscv_cost->fp_div_sf;
+    return COSTS_N_INSNS (double_insns);
+  return COSTS_N_INSNS (single_insns);
 }
 
 /* Return the cost of sign-extending OP to mode MODE, not including the
@@ -1533,73 +1441,40 @@ riscv_rtx_costs (rtx x, int code, int ou
   enum machine_mode mode = GET_MODE (x);
   bool float_mode_p = FLOAT_MODE_P (mode);
   int cost;
-  rtx addr;
-
-  /* The cost of a COMPARE is hard to define for RISCV.  COMPAREs don't
-     appear in the instruction stream, and the cost of a comparison is
-     really the cost of the branch or scc condition.  At the time of
-     writing, GCC only uses an explicit outer COMPARE code when optabs
-     is testing whether a constant is expensive enough to force into a
-     register.  We want optabs to pass such constants through the RISCV
-     expanders instead, so make all constants very cheap here.  */
-  if (outer_code == COMPARE)
-    {
-      gcc_assert (CONSTANT_P (x));
-      *total = 0;
-      return true;
-    }
 
   switch (code)
     {
     case CONST_INT:
-      /* When not optimizing for size, we care more about the cost
-         of hot code, and hot code is often in a loop.  If a constant
-         operand needs to be forced into a register, we will often be
-         able to hoist the constant load out of the loop, so the load
-         should not contribute to the cost.  */
-      if (!optimize_size || riscv_immediate_operand_p (outer_code, INTVAL (x)))
-        {
-          *total = 0;
-          return true;
-        }
+      if (riscv_immediate_operand_p (outer_code, INTVAL (x)))
+	{
+	  *total = 0;
+	  return true;
+	}
       /* Fall through.  */
 
-    case CONST:
     case SYMBOL_REF:
     case LABEL_REF:
     case CONST_DOUBLE:
-      cost = riscv_const_insns (x);
-      if (cost > 0)
-	{
-	  /* If the constant is likely to be stored in a GPR, SETs of
-	     single-insn constants are as cheap as register sets; we
-	     never want to CSE them. */
-	  if (cost == 1 && outer_code == SET && code == CONST_INT)
-	    cost = 0;
-	  *total = COSTS_N_INSNS (cost);
-	  return true;
-	}
-      /* The value will need to be fetched from the constant pool.  */
-      *total = CONSTANT_POOL_COST;
+    case CONST:
+      if (speed)
+	*total = 1;
+      else if ((cost = riscv_const_insns (x)) > 0)
+	*total = COSTS_N_INSNS (cost);
+      else /* The instruction will be fetched from the constant pool.  */
+	*total = COSTS_N_INSNS (riscv_symbol_insns (SYMBOL_ABSOLUTE));
       return true;
 
     case MEM:
       /* If the address is legitimate, return the number of
 	 instructions it needs.  */
-      addr = XEXP (x, 0);
-      cost = riscv_address_insns (addr, mode, true);
-      if (cost > 0)
+      if ((cost = riscv_address_insns (XEXP (x, 0), mode, true)) > 0)
 	{
-	  *total = COSTS_N_INSNS (cost + riscv_cost->memory_latency);
+	  *total = COSTS_N_INSNS (cost + tune_info->memory_cost);
 	  return true;
 	}
       /* Otherwise use the default handling.  */
       return false;
 
-    case FFS:
-      *total = COSTS_N_INSNS (6);
-      return false;
-
     case NOT:
       *total = COSTS_N_INSNS (GET_MODE_SIZE (mode) > UNITS_PER_WORD ? 2 : 1);
       return false;
@@ -1608,30 +1483,21 @@ riscv_rtx_costs (rtx x, int code, int ou
     case IOR:
     case XOR:
       /* Double-word operations use two single-word operations.  */
-      *total = riscv_binary_cost (x, 1, 2, speed);
-      return true;
+      *total = riscv_binary_cost (x, 1, 2);
+      return false;
 
     case ASHIFT:
     case ASHIFTRT:
     case LSHIFTRT:
-    case ROTATE:
-    case ROTATERT:
-      if (CONSTANT_P (XEXP (x, 1)))
-	*total = riscv_binary_cost (x, 1, 4, speed);
-      else
-	*total = riscv_binary_cost (x, 1, 12, speed);
-      return true;
+      *total = riscv_binary_cost (x, 1, CONSTANT_P (XEXP (x, 1)) ? 4 : 9);
+      return false;
 
     case ABS:
-      if (float_mode_p)
-        *total = riscv_cost->fp_add;
-      else
-        *total = COSTS_N_INSNS (4);
+      *total = COSTS_N_INSNS (float_mode_p ? 1 : 3);
       return false;
 
     case LO_SUM:
-      *total = (COSTS_N_INSNS (1)
-		+ set_src_cost (XEXP (x, 0), speed));
+      *total = set_src_cost (XEXP (x, 0), speed);
       return true;
 
     case LT:
@@ -1649,13 +1515,11 @@ riscv_rtx_costs (rtx x, int code, int ou
       /* Branch comparisons have VOIDmode, so use the first operand's
 	 mode instead.  */
       mode = GET_MODE (XEXP (x, 0));
-      if (FLOAT_MODE_P (mode))
-	{
-	  *total = riscv_cost->fp_add;
-	  return false;
-	}
-      *total = riscv_binary_cost (x, 1, 4, speed);
-      return true;
+      if (float_mode_p)
+	*total = tune_info->fp_add[mode == DFmode];
+      else
+	*total = riscv_binary_cost (x, 1, 3);
+      return false;
 
     case MINUS:
       if (float_mode_p
@@ -1668,7 +1532,7 @@ riscv_rtx_costs (rtx x, int code, int ou
 	  rtx op1 = XEXP (x, 1);
 	  if (GET_CODE (op0) == MULT && GET_CODE (XEXP (op0, 0)) == NEG)
 	    {
-	      *total = (riscv_fp_mult_cost (mode)
+	      *total = (tune_info->fp_mul[mode == DFmode]
 			+ set_src_cost (XEXP (XEXP (op0, 0), 0), speed)
 			+ set_src_cost (XEXP (op0, 1), speed)
 			+ set_src_cost (op1, speed));
@@ -1676,7 +1540,7 @@ riscv_rtx_costs (rtx x, int code, int ou
 	    }
 	  if (GET_CODE (op1) == MULT)
 	    {
-	      *total = (riscv_fp_mult_cost (mode)
+	      *total = (tune_info->fp_mul[mode == DFmode]
 			+ set_src_cost (op0, speed)
 			+ set_src_cost (XEXP (op1, 0), speed)
 			+ set_src_cost (XEXP (op1, 1), speed));
@@ -1687,19 +1551,10 @@ riscv_rtx_costs (rtx x, int code, int ou
 
     case PLUS:
       if (float_mode_p)
-	{
-	  /* If this is part of a MADD or MSUB, treat the PLUS as
-	     being free.  */
-	  if (GET_CODE (XEXP (x, 0)) == MULT)
-	    *total = 0;
-	  else
-	    *total = riscv_cost->fp_add;
-	  return false;
-	}
-
-      /* Double-word operations require three ADDs and an SLTU. */
-      *total = riscv_binary_cost (x, 1, 4, speed);
-      return true;
+	*total = tune_info->fp_add[mode == DFmode];
+      else
+	*total = riscv_binary_cost (x, 1, 4);
+      return false;
 
     case NEG:
       if (float_mode_p
@@ -1712,7 +1567,7 @@ riscv_rtx_costs (rtx x, int code, int ou
 	  if ((GET_CODE (op) == PLUS || GET_CODE (op) == MINUS)
 	      && GET_CODE (XEXP (op, 0)) == MULT)
 	    {
-	      *total = (riscv_fp_mult_cost (mode)
+	      *total = (tune_info->fp_mul[mode == DFmode]
 			+ set_src_cost (XEXP (XEXP (op, 0), 0), speed)
 			+ set_src_cost (XEXP (XEXP (op, 0), 1), speed)
 			+ set_src_cost (XEXP (op, 1), speed));
@@ -1721,59 +1576,38 @@ riscv_rtx_costs (rtx x, int code, int ou
 	}
 
       if (float_mode_p)
-	*total = riscv_cost->fp_add;
+	*total = tune_info->fp_add[mode == DFmode];
       else
 	*total = COSTS_N_INSNS (GET_MODE_SIZE (mode) > UNITS_PER_WORD ? 4 : 1);
       return false;
 
     case MULT:
       if (float_mode_p)
-	*total = riscv_fp_mult_cost (mode);
-      else if (mode == DImode && !TARGET_64BIT)
-	/* We use a MUL and a MULH[[S]U]. */
-	*total = riscv_cost->int_mult_si * 2;
+	*total = tune_info->fp_mul[mode == DFmode];
+      else if (GET_MODE_SIZE (mode) > UNITS_PER_WORD)
+	*total = 3 * tune_info->int_mul[0] + COSTS_N_INSNS (2);
       else if (!speed)
-	*total = 1;
-      else if (mode == DImode)
-	*total = riscv_cost->int_mult_di;
+	*total = COSTS_N_INSNS (1);
       else
-	*total = riscv_cost->int_mult_si;
+	*total = tune_info->int_mul[mode == DImode];
       return false;
 
     case DIV:
-      /* Check for a reciprocal.  */
-      if (float_mode_p
-	  && flag_unsafe_math_optimizations
-	  && XEXP (x, 0) == CONST1_RTX (mode))
-	{
-	  if (outer_code == SQRT || GET_CODE (XEXP (x, 1)) == SQRT)
-	    /* An rsqrt<mode>a or rsqrt<mode>b pattern.  Count the
-	       division as being free.  */
-	    *total = set_src_cost (XEXP (x, 1), speed);
-	  else
-	    *total = (riscv_fp_div_cost (mode)
-		      + set_src_cost (XEXP (x, 1), speed));
-	  return true;
-	}
-      /* Fall through.  */
-
     case SQRT:
     case MOD:
       if (float_mode_p)
 	{
-	  *total = riscv_fp_div_cost (mode);
+	  *total = tune_info->fp_div[mode == DFmode];
 	  return false;
 	}
       /* Fall through.  */
 
     case UDIV:
     case UMOD:
-      if (!speed)
-	*total = 1;
-      else if (mode == DImode)
-        *total = riscv_cost->int_div_di;
+      if (speed)
+	*total = tune_info->int_div[mode == DImode];
       else
-	*total = riscv_cost->int_div_si;
+	*total = COSTS_N_INSNS (1);
       return false;
 
     case SIGN_EXTEND:
@@ -1789,7 +1623,7 @@ riscv_rtx_costs (rtx x, int code, int ou
     case FIX:
     case FLOAT_EXTEND:
     case FLOAT_TRUNCATE:
-      *total = riscv_cost->fp_add;
+      *total = tune_info->fp_add[mode == DFmode];
       return false;
 
     default:
@@ -1941,12 +1775,12 @@ riscv_output_move (rtx dest, rtx src)
 	return "lui\t%0,%h1";
 
       if (symbolic_operand (src, VOIDmode))
-	{
-	  if (SYMBOL_REF_LOCAL_P (src)
-	      || (src_code == LABEL_REF && !LABEL_REF_NONLOCAL_P (src)))
-	    return "lla\t%0,%1";
-	  return "la\t%0,%1";
-	}
+	switch (riscv_classify_symbolic_expression (src))
+	  {
+	  case SYMBOL_GOT_DISP: return "la\t%0,%1";
+	  case SYMBOL_ABSOLUTE: return "lla\t%0,%1";
+	  default: gcc_unreachable();
+	  }
     }
   if (src_code == REG && FP_REG_P (REGNO (src)))
     {
@@ -2132,17 +1966,47 @@ riscv_emit_compare (enum rtx_code *code,
 
   if (GET_MODE_CLASS (GET_MODE (*op0)) == MODE_INT)
     {
-      if (*op1 == const0_rtx)
-	;
-      else if ((*code == EQ || *code == NE) && CONST_INT_P (cmp_op1)
-	       && SMALL_OPERAND (-INTVAL (cmp_op1)))
+      if (splittable_const_int_operand (cmp_op1, VOIDmode))
 	{
-	  *op0 = gen_reg_rtx (GET_MODE (cmp_op0));
-	  riscv_emit_binary (PLUS, *op0, cmp_op0, GEN_INT (-INTVAL (cmp_op1)));
-	  *op1 = const0_rtx;
+	  HOST_WIDE_INT rhs = INTVAL (cmp_op1), new_rhs;
+	  enum rtx_code new_code;
+
+	  switch (*code)
+	    {
+	    case LTU: new_rhs = rhs - 1; new_code = LEU; goto try_new_rhs;
+	    case LEU: new_rhs = rhs + 1; new_code = LTU; goto try_new_rhs;
+	    case GTU: new_rhs = rhs + 1; new_code = GEU; goto try_new_rhs;
+	    case GEU: new_rhs = rhs - 1; new_code = GTU; goto try_new_rhs;
+	    case LT: new_rhs = rhs - 1; new_code = LE; goto try_new_rhs;
+	    case LE: new_rhs = rhs + 1; new_code = LT; goto try_new_rhs;
+	    case GT: new_rhs = rhs + 1; new_code = GE; goto try_new_rhs;
+	    case GE: new_rhs = rhs - 1; new_code = GT;
+	    try_new_rhs:
+	      /* Convert e.g. OP0 > 4095 into OP0 >= 4096.  */
+	      if ((rhs < 0) == (new_rhs < 0)
+		  && riscv_integer_cost (new_rhs) < riscv_integer_cost (rhs))
+		{
+		  *op1 = GEN_INT (new_rhs);
+		  *code = new_code;
+		}
+	      break;
+
+	    case EQ:
+	    case NE:
+	      /* Convert e.g. OP0 == 2048 into OP0 - 2048 == 0.  */
+	      if (SMALL_OPERAND (-rhs))
+		{
+		  *op0 = gen_reg_rtx (GET_MODE (cmp_op0));
+		  riscv_emit_binary (PLUS, *op0, cmp_op0, GEN_INT (-rhs));
+		  *op1 = const0_rtx;
+		}
+	    default:
+	      break;
+	    }
 	}
-      else if (*op1 != const0_rtx)
-	*op1 = force_reg (GET_MODE (cmp_op0), cmp_op1);
+
+      if (*op1 != const0_rtx)
+	*op1 = force_reg (GET_MODE (cmp_op0), *op1);
     }
   else
     {
@@ -2638,7 +2502,7 @@ riscv_function_value (const_tree valtype
 }
 
 /* Implement TARGET_RETURN_IN_MEMORY.  Scalars and small structures
-   that fit in two registers are returned in v0/v1. */
+   that fit in two registers are returned in a0/a1. */
 
 static bool
 riscv_return_in_memory (const_tree type, const_tree fndecl ATTRIBUTE_UNUSED)
@@ -2909,15 +2773,16 @@ riscv_init_relocs (void)
   memset (riscv_hi_relocs, '\0', sizeof (riscv_hi_relocs));
   memset (riscv_lo_relocs, '\0', sizeof (riscv_lo_relocs));
 
-  if (!flag_pic)
+  if (!flag_pic && riscv_cmodel == CM_MEDLOW)
     {
       riscv_hi_relocs[SYMBOL_ABSOLUTE] = "%hi(";
       riscv_lo_relocs[SYMBOL_ABSOLUTE] = "%lo(";
+    }
 
+  if (!flag_pic || flag_pie)
+    {
       riscv_hi_relocs[SYMBOL_TLS_LE] = "%tprel_hi(";
       riscv_lo_relocs[SYMBOL_TLS_LE] = "%tprel_lo(";
-
-      riscv_lo_relocs[SYMBOL_TLS_IE] = "%tls_ie_off(";
     }
 }
 
@@ -3059,7 +2924,7 @@ riscv_print_operand_address (FILE *file,
   gcc_unreachable ();
 }
 
-bool
+static bool
 riscv_size_ok_for_small_data_p (int size)
 {
   return g_switch_value && IN_RANGE (size, 1, g_switch_value);
@@ -3126,7 +2991,7 @@ riscv_output_dwarf_dtprel (FILE *file, i
       gcc_unreachable ();
     }
   output_addr_const (file, x);
-  fputs ("+0x8000", file);
+  fputs ("+0x800", file);
 }
 
 /* Make the last instruction frame-related and note that it performs
@@ -3181,21 +3046,16 @@ riscv_save_reg_p (unsigned int regno)
 	|                               |
 	|  incoming stack arguments     |
 	|                               |
-	+-------------------------------+
-	|                               |
-	|  caller-allocated save area   |
-      A |  for register arguments       |
-	|                               |
 	+-------------------------------+ <-- incoming stack pointer
 	|                               |
 	|  callee-allocated save area   |
-      B |  for arguments that are       |
+	|  for arguments that are       |
 	|  split between registers and  |
 	|  the stack                    |
 	|                               |
 	+-------------------------------+ <-- arg_pointer_rtx
 	|                               |
-      C |  callee-allocated save area   |
+	|  callee-allocated save area   |
 	|  for register varargs         |
 	|                               |
 	+-------------------------------+ <-- hard_frame_pointer_rtx;
@@ -3214,15 +3074,8 @@ riscv_save_reg_p (unsigned int regno)
 	|                               |
 	|  outgoing stack arguments     |
 	|                               |
-	+-------------------------------+
-	|                               |
-	|  caller-allocated save area   |
-	|  for register arguments       |
-	|                               |
 	+-------------------------------+ <-- stack_pointer_rtx
 
-   At least two of A, B and C will be empty.
-
    Dynamic stack allocations such as alloca insert data at point P.
    They decrease stack_pointer_rtx but leave frame_pointer_rtx and
    hard_frame_pointer_rtx unchanged.  */
@@ -3457,7 +3310,7 @@ riscv_expand_prologue (void)
   frame = &cfun->machine->frame;
   size = frame->total_size;
 
-  if (flag_stack_usage)
+  if (flag_stack_usage_info)
     current_function_static_stack_size = size;
 
   /* Save the registers.  Allocate up to RISCV_MAX_FIRST_STACK_STEP
@@ -3588,7 +3441,10 @@ riscv_expand_epilogue (bool sibcall_p)
 			      EH_RETURN_STACKADJ_RTX));
 
   if (!sibcall_p)
-    emit_jump_insn (gen_return_internal (gen_rtx_REG (Pmode, RETURN_ADDR_REGNUM)));
+    {
+      rtx ra = gen_rtx_REG (Pmode, RETURN_ADDR_REGNUM);
+      emit_jump_insn (gen_simple_return_internal (ra));
+    }
 }
 
 /* Return nonzero if this function is known to have a null epilogue.
@@ -3607,29 +3463,25 @@ riscv_can_use_return_insn (void)
 static bool
 riscv_hard_regno_mode_ok_p (unsigned int regno, enum machine_mode mode)
 {
-  unsigned int size;
-  enum mode_class mclass;
+  unsigned int size = GET_MODE_SIZE (mode);
+  enum mode_class mclass = GET_MODE_CLASS (mode);
 
   /* This is hella bogus but ira_build segfaults on RV32 without it. */
   if (VECTOR_MODE_P (mode))
     return true;
 
-  if (mode == CCmode)
-    return GP_REG_P (regno);
-
-  size = GET_MODE_SIZE (mode);
-  mclass = GET_MODE_CLASS (mode);
-
   if (GP_REG_P (regno))
-    /* Double-word values must be even-register-aligned. */
-    return ((regno - GP_REG_FIRST) & 1) == 0 || size <= UNITS_PER_WORD;
-
-  if (FP_REG_P (regno))
     {
-      /* Allow TFmode for CCmode reloads.  */
-      if (mode == TFmode)
+      if (size <= UNITS_PER_WORD)
 	return true;
 
+      /* Double-word values must be even-register-aligned.  */
+      if (size <= 2 * UNITS_PER_WORD)
+	return regno % 2 == 0;
+    }
+
+  if (FP_REG_P (regno))
+    {
       if (mclass == MODE_FLOAT
 	  || mclass == MODE_COMPLEX_FLOAT
 	  || mclass == MODE_VECTOR_FLOAT)
@@ -3694,45 +3546,6 @@ riscv_canonicalize_move_class (reg_class
   return rclass;
 }
 
-/* Return the cost of moving a value of mode MODE from a register of
-   class FROM to a GPR.  Return 0 for classes that are unions of other
-   classes handled by this function.  */
-
-static int
-riscv_move_to_gpr_cost (reg_class_t from)
-{
-  switch (from)
-    {
-    case GENERAL_REGS:
-      return 1;
-
-    case FP_REGS:
-      /* FP->int moves can cause recoupling on decoupled implementations */
-      return 4;
-
-    default:
-      return 0;
-    }
-}
-
-/* Return the cost of moving a value of mode MODE from a GPR to a
-   register of class TO.  Return 0 for classes that are unions of
-   other classes handled by this function.  */
-
-static int
-riscv_move_from_gpr_cost (reg_class_t to)
-{
-  switch (to)
-    {
-    case GENERAL_REGS:
-    case FP_REGS:
-      return 1;
-
-    default:
-      return 0;
-    }
-}
-
 /* Implement TARGET_REGISTER_MOVE_COST.  Return 0 for classes that are the
    maximum of the move costs for subclasses; regclass will work out
    the maximum for us.  */
@@ -3741,30 +3554,16 @@ static int
 riscv_register_move_cost (enum machine_mode mode ATTRIBUTE_UNUSED,
 			 reg_class_t from, reg_class_t to)
 {
-  int cost1, cost2;
-
   from = riscv_canonicalize_move_class (from);
   to = riscv_canonicalize_move_class (to);
 
-  /* Handle moves that can be done without using general-purpose registers.  */
-  if (from == FP_REGS && to == FP_REGS)
-      /* fmv.fmt.  */
-      return 1;
+  if ((from == GENERAL_REGS && to == GENERAL_REGS)
+      || (from == GENERAL_REGS && to == FP_REGS)
+      || (from == FP_REGS && to == FP_REGS))
+    return COSTS_N_INSNS (1);
 
-  /* Handle cases in which only one class deviates from the ideal.  */
-  if (from == GENERAL_REGS)
-    return riscv_move_from_gpr_cost (to);
-  if (to == GENERAL_REGS)
-    return riscv_move_to_gpr_cost (from);
-
-  /* Handles cases that require a GPR temporary.  */
-  cost1 = riscv_move_to_gpr_cost (from);
-  if (cost1 != 0)
-    {
-      cost2 = riscv_move_from_gpr_cost (to);
-      if (cost2 != 0)
-	return cost1 + cost2;
-    }
+  if (from == FP_REGS && to == GENERAL_REGS)
+    return tune_info->fp_to_int_cost;
 
   return 0;
 }
@@ -3774,7 +3573,7 @@ riscv_register_move_cost (enum machine_m
 static int
 riscv_memory_move_cost (enum machine_mode mode, reg_class_t rclass, bool in)
 {
-  return (riscv_cost->memory_latency
+  return (tune_info->memory_cost
 	  + memory_move_secondary_cost (mode, rclass, in));
 } 
 
@@ -3861,14 +3660,7 @@ riscv_adjust_cost (rtx insn ATTRIBUTE_UN
 static int
 riscv_issue_rate (void)
 {
-  switch (riscv_tune)
-    {
-    case PROCESSOR_ROCKET:
-      return 1;
-
-    default:
-      return 1;
-    }
+  return tune_info->issue_rate;
 }
 
 /* This structure describes a single built-in function.  */
@@ -4152,159 +3944,6 @@ riscv_expand_builtin (tree exp, rtx targ
   gcc_unreachable ();
 }
 
-/* This structure records that the current function has a LO_SUM
-   involving SYMBOL_REF or LABEL_REF BASE and that MAX_OFFSET is
-   the largest offset applied to BASE by all such LO_SUMs.  */
-struct riscv_lo_sum_offset {
-  rtx base;
-  HOST_WIDE_INT offset;
-};
-
-/* Return a hash value for SYMBOL_REF or LABEL_REF BASE.  */
-
-static hashval_t
-riscv_hash_base (rtx base)
-{
-  int do_not_record_p;
-
-  return hash_rtx (base, GET_MODE (base), &do_not_record_p, NULL, false);
-}
-
-/* Hash-table callbacks for riscv_lo_sum_offsets.  */
-
-static hashval_t
-riscv_lo_sum_offset_hash (const void *entry)
-{
-  return riscv_hash_base (((const struct riscv_lo_sum_offset *) entry)->base);
-}
-
-static int
-riscv_lo_sum_offset_eq (const void *entry, const void *value)
-{
-  return rtx_equal_p (((const struct riscv_lo_sum_offset *) entry)->base,
-		      (const_rtx) value);
-}
-
-/* Look up symbolic constant X in HTAB, which is a hash table of
-   riscv_lo_sum_offsets.  If OPTION is NO_INSERT, return true if X can be
-   paired with a recorded LO_SUM, otherwise record X in the table.  */
-
-static bool
-riscv_lo_sum_offset_lookup (htab_t htab, rtx x, enum insert_option option)
-{
-  rtx base, offset;
-  void **slot;
-  struct riscv_lo_sum_offset *entry;
-
-  /* Split X into a base and offset.  */
-  split_const (x, &base, &offset);
-  if (UNSPEC_ADDRESS_P (base))
-    base = UNSPEC_ADDRESS (base);
-
-  /* Look up the base in the hash table.  */
-  slot = htab_find_slot_with_hash (htab, base, riscv_hash_base (base), option);
-  if (slot == NULL)
-    return false;
-
-  entry = (struct riscv_lo_sum_offset *) *slot;
-  if (option == INSERT)
-    {
-      if (entry == NULL)
-	{
-	  entry = XNEW (struct riscv_lo_sum_offset);
-	  entry->base = base;
-	  entry->offset = INTVAL (offset);
-	  *slot = entry;
-	}
-      else
-	{
-	  if (INTVAL (offset) > entry->offset)
-	    entry->offset = INTVAL (offset);
-	}
-    }
-  return INTVAL (offset) <= entry->offset;
-}
-
-/* A for_each_rtx callback for which DATA is a riscv_lo_sum_offset hash table.
-   Record every LO_SUM in *LOC.  */
-
-static int
-riscv_record_lo_sum (rtx *loc, void *data)
-{
-  if (GET_CODE (*loc) == LO_SUM)
-    riscv_lo_sum_offset_lookup ((htab_t) data, XEXP (*loc, 1), INSERT);
-  return 0;
-}
-
-/* Return true if INSN is a SET of an orphaned high-part relocation.
-   HTAB is a hash table of riscv_lo_sum_offsets that describes all the
-   LO_SUMs in the current function.  */
-
-static bool
-riscv_orphaned_high_part_p (htab_t htab, rtx insn)
-{
-  rtx x, set;
-
-  set = single_set (insn);
-  if (set)
-    {
-      /* Check for %his.  */
-      x = SET_SRC (set);
-      if (GET_CODE (x) == HIGH
-	  && absolute_symbolic_operand (XEXP (x, 0), VOIDmode))
-	return !riscv_lo_sum_offset_lookup (htab, XEXP (x, 0), NO_INSERT);
-    }
-  return false;
-}
-
-/* Delete any high-part relocations whose partnering low parts are dead. */
-
-static void
-riscv_reorg_process_insns (void)
-{
-  rtx insn, next_insn;
-  htab_t htab;
-
-  /* Force all instructions to be split into their final form.  */
-  split_all_insns_noflow ();
-
-  /* Recalculate instruction lengths without taking nops into account.  */
-  shorten_branches (get_insns ());
-
-  htab = htab_create (37, riscv_lo_sum_offset_hash,
-		      riscv_lo_sum_offset_eq, free);
-
-  /* Make a first pass over the instructions, recording all the LO_SUMs.  */
-  for (insn = get_insns (); insn != 0; insn = NEXT_INSN (insn))
-    if (USEFUL_INSN_P (insn))
-      for_each_rtx (&PATTERN (insn), riscv_record_lo_sum, htab);
-
-  /* Make a second pass over the instructions.  Delete orphaned
-     high-part relocations or turn them into NOPs.  Avoid hazards
-     by inserting NOPs.  */
-  for (insn = get_insns (); insn != 0; insn = next_insn)
-    {
-      next_insn = NEXT_INSN (insn);
-      if (USEFUL_INSN_P (insn))
-	{
-	  /* INSN is a single instruction.  Delete it if it's an
-	     orphaned high-part relocation.  */
-	  if (riscv_orphaned_high_part_p (htab, insn))
-	    delete_insn (insn);
-	}
-    }
-
-  htab_delete (htab);
-}
-
-/* Implement TARGET_MACHINE_DEPENDENT_REORG.  */
-
-static void
-riscv_reorg (void)
-{
-  riscv_reorg_process_insns ();
-}
-
 /* Implement TARGET_ASM_OUTPUT_MI_THUNK.  Generate rtl rather than asm text
    in order to avoid duplicating too much logic from elsewhere.  */
 
@@ -4327,8 +3966,8 @@ riscv_output_mi_thunk (FILE *file, tree 
   use_sibcall_p = absolute_symbolic_operand (fnaddr, Pmode);
 
   /* We need two temporary registers in some cases.  */
-  temp1 = gen_rtx_REG (Pmode, GP_RETURN);
-  temp2 = gen_rtx_REG (Pmode, GP_RETURN + 1);
+  temp1 = gen_rtx_REG (Pmode, GP_TEMP_FIRST);
+  temp2 = gen_rtx_REG (Pmode, GP_TEMP_FIRST + 1);
 
   /* Find out which register contains the "this" pointer.  */
   if (aggregate_value_p (TREE_TYPE (TREE_TYPE (function)), function))
@@ -4399,60 +4038,21 @@ riscv_init_machine_status (void)
   return ggc_alloc_cleared_machine_function ();
 }
 
-/* Return the riscv_cpu_info entry for the processor or ISA given
-   by CPU_STRING.  Return null if the string isn't recognized.
-
-   A similar function exists in GAS.  */
-
-static const struct riscv_cpu_info *
-riscv_parse_cpu (const char *cpu_string)
-{
-  unsigned int i;
-
-  for (i = 0; i < ARRAY_SIZE (riscv_cpu_info_table); i++)
-    if (strcmp (riscv_cpu_info_table[i].name, cpu_string) == 0)
-      return riscv_cpu_info_table + i;
-
-  return NULL;
-}
-
 /* Implement TARGET_OPTION_OVERRIDE.  */
 
 static void
 riscv_option_override (void)
 {
   int regno, mode;
-  const struct riscv_cpu_info *info;
+  const struct riscv_cpu_info *cpu;
 
 #ifdef SUBTARGET_OVERRIDE_OPTIONS
   SUBTARGET_OVERRIDE_OPTIONS;
 #endif
 
-  info = riscv_parse_cpu (RISCV_CPU_STRING_DEFAULT);
-  gcc_assert (info);
-  riscv_tune = info->cpu;
-
-  if (riscv_tune_string != 0)
-    {
-      const struct riscv_cpu_info *tune = riscv_parse_cpu (riscv_tune_string);
-      if (tune)
-	riscv_tune = tune->cpu;
-    }
-
   flag_pcc_struct_return = 0;
 
-  /* Decide which rtx_costs structure to use.  */
-  if (optimize_size)
-    riscv_cost = &riscv_rtx_cost_optimize_size;
-  else
-    riscv_cost = &riscv_rtx_cost_data[riscv_tune];
-
-  /* If the user hasn't specified a branch cost, use the processor's
-     default.  */
-  if (riscv_branch_cost == 0)
-    riscv_branch_cost = riscv_cost->branch_cost;
-
-  if (!TARGET_USE_GP)
+  if (flag_pic)
     g_switch_value = 0;
 
   /* Prefer a call to memcpy over inline code when optimizing for size,
@@ -4460,9 +4060,15 @@ riscv_option_override (void)
   if (optimize_size && (target_flags_explicit & MASK_MEMCPY) == 0)
     target_flags |= MASK_MEMCPY;
 
-  /* Use atomic instructions, if user did not specify a preference */
-  if ((target_flags_explicit & MASK_ATOMIC) == 0)
-    target_flags |= MASK_ATOMIC;
+  /* Handle -mtune.  */
+  cpu = riscv_parse_cpu (riscv_tune_string ? riscv_tune_string :
+			 RISCV_TUNE_STRING_DEFAULT);
+  tune_info = optimize_size ? &optimize_size_tune_info : cpu->tune_info;
+
+  /* If the user hasn't specified a branch cost, use the processor's
+     default.  */
+  if (riscv_branch_cost == 0)
+    riscv_branch_cost = tune_info->branch_cost;
 
   /* Set up riscv_hard_regno_mode_ok.  */
   for (mode = 0; mode < MAX_MACHINE_MODE; mode++)
@@ -4473,6 +4079,19 @@ riscv_option_override (void)
   /* Function to allocate machine-dependent function status.  */
   init_machine_status = &riscv_init_machine_status;
 
+  if (riscv_cmodel_string)
+    {
+      if (strcmp (riscv_cmodel_string, "medlow") == 0)
+	riscv_cmodel = CM_MEDLOW;
+      else if (strcmp (riscv_cmodel_string, "medany") == 0)
+	riscv_cmodel = CM_MEDANY;
+      else
+	error ("unsupported code model: %s", riscv_cmodel_string);
+    }
+
+  if (flag_pic)
+    riscv_cmodel = CM_PIC;
+
   riscv_init_relocs ();
 }
 
@@ -4513,10 +4132,10 @@ riscv_trampoline_init (rtx m_tramp, tree
 #define OP(X) gen_int_mode (X, SImode)
 #define MATCH_LREG ((Pmode) == DImode ? MATCH_LD : MATCH_LW)
 
-  /* auipc   v0, 0
-     l[wd]   v1, target_function_offset(v0)
-     l[wd]   $static_chain, static_chain_offset(v0)
-     jr      v1
+  /* auipc   t0, 0
+     l[wd]   t1, target_function_offset(t0)
+     l[wd]   $static_chain, static_chain_offset(t0)
+     jr      t1
   */
 
   trampoline[0] = OP (RISCV_UTYPE (AUIPC, STATIC_CHAIN_REGNUM, 0));
@@ -4549,6 +4168,12 @@ riscv_trampoline_init (rtx m_tramp, tree
   emit_insn (gen_clear_cache (addr, end_addr));
 }
 
+static bool
+riscv_lra_p (void)
+{
+  return riscv_lra_flag;
+}
+
 /* Initialize the GCC target structure.  */
 #undef TARGET_ASM_ALIGNED_HI_OP
 #define TARGET_ASM_ALIGNED_HI_OP "\t.half\t"
@@ -4580,9 +4205,6 @@ riscv_trampoline_init (rtx m_tramp, tree
 #undef TARGET_ADDRESS_COST
 #define TARGET_ADDRESS_COST riscv_address_cost
 
-#undef TARGET_MACHINE_DEPENDENT_REORG
-#define TARGET_MACHINE_DEPENDENT_REORG riscv_reorg
-
 #undef  TARGET_PREFERRED_RELOAD_CLASS
 #define TARGET_PREFERRED_RELOAD_CLASS riscv_preferred_reload_class
 
@@ -4650,9 +4272,6 @@ riscv_trampoline_init (rtx m_tramp, tree
 #undef TARGET_USE_BLOCKS_FOR_CONSTANT_P
 #define TARGET_USE_BLOCKS_FOR_CONSTANT_P hook_bool_mode_const_rtx_true
 
-#undef  TARGET_COMP_TYPE_ATTRIBUTES
-#define TARGET_COMP_TYPE_ATTRIBUTES riscv_comp_type_attributes
-
 #ifdef HAVE_AS_DTPRELWORD
 #undef TARGET_ASM_OUTPUT_DWARF_DTPREL
 #define TARGET_ASM_OUTPUT_DWARF_DTPREL riscv_output_dwarf_dtprel
@@ -4682,6 +4301,9 @@ riscv_trampoline_init (rtx m_tramp, tree
 #undef TARGET_MAX_ANCHOR_OFFSET
 #define TARGET_MAX_ANCHOR_OFFSET (RISCV_IMM_REACH/2-1)
 
+#undef TARGET_LRA_P
+#define TARGET_LRA_P riscv_lra_p
+
 struct gcc_target targetm = TARGET_INITIALIZER;
 
 #include "gt-riscv.h"
Index: src/external/gpl3/gcc/dist/gcc/config/riscv/riscv.h
diff -u src/external/gpl3/gcc/dist/gcc/config/riscv/riscv.h:1.1 src/external/gpl3/gcc/dist/gcc/config/riscv/riscv.h:1.2
--- src/external/gpl3/gcc/dist/gcc/config/riscv/riscv.h:1.1	Fri Sep 19 17:20:29 2014
+++ src/external/gpl3/gcc/dist/gcc/config/riscv/riscv.h	Fri Mar 27 01:51:34 2015
@@ -19,28 +19,6 @@ You should have received a copy of the G
 along with GCC; see the file COPYING3.  If not see
 <http://www.gnu.org/licenses/>.  */
 
-#if !defined(IN_LIBGCC2) && !defined(IN_TARGET_LIBS)
-/* Information about one recognized processor.  Defined here for the
-   benefit of TARGET_CPU_CPP_BUILTINS.  */
-struct riscv_cpu_info {
-  /* The 'canonical' name of the processor as far as GCC is concerned.
-     It's typically a manufacturer's prefix followed by a numerical
-     designation.  It should be lowercase.  */
-  const char *name;
-
-  /* The internal processor number that most closely matches this
-     entry.  Several processors can have the same value, if there's no
-     difference between them from GCC's point of view.  */
-  enum processor cpu;
-
-  /* A mask of PTF_* values.  */
-  unsigned int tune_flags;
-};
-#endif
-
-/* True if a global pointer can be used to access small data. */
-#define TARGET_USE_GP (!flag_pic)
-
 /* TARGET_HARD_FLOAT and TARGET_SOFT_FLOAT reflect whether the FPU is
    directly accessible, while the command-line options select
    TARGET_HARD_FLOAT_ABI and TARGET_SOFT_FLOAT_ABI to reflect the ABI
@@ -126,15 +104,15 @@ struct riscv_cpu_info {
 /* Default target_flags if no switches are specified  */
 
 #ifndef TARGET_DEFAULT
-#define TARGET_DEFAULT 0
+#define TARGET_DEFAULT (TARGET_ATOMIC | 
 #endif
 
-#ifndef TARGET_CPU_DEFAULT
-#define TARGET_CPU_DEFAULT 0
+#ifndef RISCV_ARCH_STRING_DEFAULT
+#define RISCV_ARCH_STRING_DEFAULT "IMAFD"
 #endif
 
-#ifndef RISCV_CPU_STRING_DEFAULT
-#define RISCV_CPU_STRING_DEFAULT "rocket"
+#ifndef RISCV_TUNE_STRING_DEFAULT
+#define RISCV_TUNE_STRING_DEFAULT "rocket"
 #endif
 
 #ifndef TARGET_64BIT_DEFAULT
@@ -184,15 +162,9 @@ struct riscv_cpu_info {
 #define NM_FLAGS "-Bn"
 #endif
 
-/* SUBTARGET_ASM_SPEC is always passed to the assembler.  It may be
-   overridden by subtargets.  */
-
-#ifndef SUBTARGET_ASM_SPEC
-#define SUBTARGET_ASM_SPEC ""
-#endif
-
 #undef ASM_SPEC
 #define ASM_SPEC "\
+%(subtarget_asm_debugging_spec) \
 %{m32} %{m64} %{!m32:%{!m64: %(asm_abi_default_spec)}} \
 %{fPIC|fpic|fPIE|fpie:-fpic} \
 %{march=*} \
@@ -208,31 +180,6 @@ struct riscv_cpu_info {
 %{shared}"
 #endif  /* LINK_SPEC defined */
 
-
-/* Specs for the compiler proper */
-
-/* SUBTARGET_CC1_SPEC is passed to the compiler proper.  It may be
-   overridden by subtargets.  */
-#ifndef SUBTARGET_CC1_SPEC
-#define SUBTARGET_CC1_SPEC ""
-#endif
-
-/* CC1_SPEC is the set of arguments to pass to the compiler proper.  */
-
-#undef CC1_SPEC
-#define CC1_SPEC "\
-%(subtarget_cc1_spec)"
-
-/* Preprocessor specs.  */
-
-/* SUBTARGET_CPP_SPEC is passed to the preprocessor.  It may be
-   overridden by subtargets.  */
-#ifndef SUBTARGET_CPP_SPEC
-#define SUBTARGET_CPP_SPEC ""
-#endif
-
-#define CPP_SPEC "%(subtarget_cpp_spec)"
-
 /* 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.
@@ -244,9 +191,6 @@ struct riscv_cpu_info {
    Do not define this macro if it does not need to do anything.  */
 
 #define EXTRA_SPECS							\
-  { "subtarget_cc1_spec", SUBTARGET_CC1_SPEC },				\
-  { "subtarget_cpp_spec", SUBTARGET_CPP_SPEC },				\
-  { "subtarget_asm_spec", SUBTARGET_ASM_SPEC },				\
   { "asm_abi_default_spec", "-" MULTILIB_ARCH_DEFAULT },		\
   SUBTARGET_EXTRA_SPECS
 
@@ -254,18 +198,15 @@ struct riscv_cpu_info {
 #define SUBTARGET_EXTRA_SPECS
 #endif
 
-#ifndef PREFERRED_DEBUGGING_TYPE
-#define PREFERRED_DEBUGGING_TYPE DWARF2_DEBUG
-#endif
-
-#define DWARF2_ADDR_SIZE UNITS_PER_WORD
-
 /* By default, turn on GDB extensions.  */
 #define DEFAULT_GDB_EXTENSIONS 1
 
 #define LOCAL_LABEL_PREFIX	"."
 #define USER_LABEL_PREFIX	""
 
+#define DWARF2_DEBUGGING_INFO 1
+#define DWARF2_ASM_LINE_DEBUG_INFO 0
+
 /* The mapping from gcc register number to DWARF 2 CFA column number.  */
 #define DWARF_FRAME_REGNUM(REGNO) \
   (GP_REG_P (REGNO) || FP_REG_P (REGNO) ? REGNO : INVALID_REGNUM)
@@ -286,11 +227,6 @@ struct riscv_cpu_info {
 
 #define EH_RETURN_STACKADJ_RTX  gen_rtx_REG (Pmode, GP_ARG_FIRST + 4)
 
-/* Offsets recorded in opcodes are a multiple of this alignment factor.
-   The default for this in 64-bit mode is 8, which causes problems with
-   SFmode register saves.  */
-#define DWARF_CIE_DATA_ALIGNMENT -4
-
 /* Target machine storage layout */
 
 #define BITS_BIG_ENDIAN 0
@@ -467,12 +403,12 @@ struct riscv_cpu_info {
 
 #define FIRST_PSEUDO_REGISTER 66
 
-/* x0, sp, tp, and gp are fixed. */
+/* x0, sp, gp, and tp are fixed. */
 
 #define FIXED_REGISTERS							\
 { /* General registers.  */                                             \
-  1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1,			\
-  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1,			\
+  1, 0, 1, 1, 1, 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, 0,			\
   /* Floating-point 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, 0, 0, 0, 0, 0, 0,			\
@@ -481,27 +417,27 @@ struct riscv_cpu_info {
 }
 
 
-/* Function calls clobber x16-30 (v0-1, a0-7, t0-4) and f16-31
-   (fv0-1, fa0-7, ft0-5).  The call RTLs themselves clobber x1 (ra). */
+/* a0-a7, t0-a6, fa0-fa7, and ft0-ft11 are volatile across calls.
+   The call RTLs themselves clobber ra.  */
 
 #define CALL_USED_REGISTERS						\
 { /* General registers.  */                                             \
-  1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1,			\
-  1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,			\
+  1, 0, 1, 1, 1, 1, 1, 1, 0, 0, 1, 1, 1, 1, 1, 1,			\
+  1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1,			\
   /* Floating-point registers.  */                                      \
-  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,			\
-  1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,			\
+  1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 1, 1, 1, 1, 1, 1,			\
+  1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1,			\
   /* Others.  */                                                        \
   1, 1 \
 }
 
 #define CALL_REALLY_USED_REGISTERS                                      \
 { /* General registers.  */                                             \
-  1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1,			\
-  1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,			\
+  1, 0, 1, 1, 1, 1, 1, 1, 0, 0, 1, 1, 1, 1, 1, 1,			\
+  1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1,			\
   /* Floating-point registers.  */                                      \
-  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,			\
-  1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,			\
+  1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 1, 1, 1, 1, 1, 1,			\
+  1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1,			\
   /* Others.  */                                                        \
   1, 1 \
 }
@@ -516,17 +452,11 @@ struct riscv_cpu_info {
 #define FP_REG_LAST  63
 #define FP_REG_NUM   (FP_REG_LAST - FP_REG_FIRST + 1)
 
-#define CALLEE_SAVED_GP_REG_FIRST (GP_REG_FIRST + 2)
-#define CALLEE_SAVED_GP_REG_LAST (CALLEE_SAVED_GP_REG_FIRST + 12 - 1)
-
-#define CALLEE_SAVED_FP_REG_FIRST (FP_REG_FIRST + 0)
-#define CALLEE_SAVED_FP_REG_LAST (CALLEE_SAVED_FP_REG_FIRST + 16 - 1)
-
 /* The DWARF 2 CFA column which tracks the return address from a
    signal handler context.  This means that to maintain backwards
    compatibility, no hard register can be assigned this column if it
    would need to be handled by the DWARF unwinder.  */
-#define DWARF_ALT_FRAME_RETURN_COLUMN 66
+#define DWARF_ALT_FRAME_RETURN_COLUMN 64
 
 #define GP_REG_P(REGNO)	\
   ((unsigned int) ((int) (REGNO) - GP_REG_FIRST) < GP_REG_NUM)
@@ -552,10 +482,9 @@ struct riscv_cpu_info {
 			  && GET_MODE_CLASS (MODE2) == MODE_INT))
 
 /* Use s0 as the frame pointer if it is so requested. */
-#define HARD_FRAME_POINTER_REGNUM 2
-#define STACK_POINTER_REGNUM 14
-#define THREAD_POINTER_REGNUM 15
-#define GP_REGNUM 31
+#define HARD_FRAME_POINTER_REGNUM 8
+#define STACK_POINTER_REGNUM 2
+#define THREAD_POINTER_REGNUM 4
 
 /* These two registers don't really exist: they get eliminated to either
    the stack or hard frame pointer.  */
@@ -566,7 +495,7 @@ struct riscv_cpu_info {
 #define HARD_FRAME_POINTER_IS_ARG_POINTER 0
 
 /* Register in which static-chain is passed to a function.  */
-#define STATIC_CHAIN_REGNUM GP_RETURN
+#define STATIC_CHAIN_REGNUM GP_TEMP_FIRST
 
 /* Registers used as temporaries in prologue/epilogue code.
 
@@ -575,8 +504,8 @@ struct riscv_cpu_info {
    The epilogue temporary mustn't conflict with the return registers,
    the frame pointer, the EH stack adjustment, or the EH data registers. */
 
-#define RISCV_PROLOGUE_TEMP_REGNUM GP_TEMP_FIRST
-#define RISCV_EPILOGUE_TEMP_REGNUM GP_TEMP_FIRST
+#define RISCV_PROLOGUE_TEMP_REGNUM (GP_TEMP_FIRST + 1)
+#define RISCV_EPILOGUE_TEMP_REGNUM RISCV_PROLOGUE_TEMP_REGNUM
 
 #define RISCV_PROLOGUE_TEMP(MODE) gen_rtx_REG (MODE, RISCV_PROLOGUE_TEMP_REGNUM)
 #define RISCV_EPILOGUE_TEMP(MODE) gen_rtx_REG (MODE, RISCV_EPILOGUE_TEMP_REGNUM)
@@ -653,7 +582,7 @@ enum reg_class
 #define REG_CLASS_CONTENTS									\
 {												\
   { 0x00000000, 0x00000000, 0x00000000 },	/* NO_REGS */		\
-  { 0x7c000000, 0x00000000, 0x00000000 },	/* T_REGS */		\
+  { 0xf00000e0, 0x00000000, 0x00000000 },	/* T_REGS */		\
   { 0xffffffff, 0x00000000, 0x00000000 },	/* GR_REGS */		\
   { 0x00000000, 0xffffffff, 0x00000000 },	/* FP_REGS */		\
   { 0x00000000, 0x00000000, 0x00000003 },	/* FRAME_REGS */	\
@@ -687,15 +616,16 @@ enum reg_class
 #define REG_ALLOC_ORDER							\
 { \
   /* Call-clobbered GPRs.  */						\
-  16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 1,	\
+  15, 14, 13, 12, 11, 10, 16, 17, 5, 6, 7, 28, 29, 30, 31, 1,		\
   /* Call-saved GPRs.  */						\
-  2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13,	       			\
+  8, 9, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27,	       			\
   /* GPRs that can never be exposed to the register allocator.  */	\
-  0,  14, 15,								\
+  0, 2, 3, 4,								\
   /* Call-clobbered FPRs.  */						\
-  48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63,	\
+  32, 33, 34, 35, 36, 37, 38, 39, 42, 43, 44, 45, 46, 47, 48, 49,	\
+  60, 61, 62, 63,							\
   /* Call-saved FPRs.  */						\
-  32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47,	\
+  40, 41, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59,			\
   /* None of the remaining classes have defined call-saved		\
      registers.  */							\
   64, 65								\
@@ -778,17 +708,17 @@ enum reg_class
 /* Symbolic macros for the registers used to return integer and floating
    point values.  */
 
-#define GP_RETURN (GP_REG_FIRST + 16)
-#define FP_RETURN ((TARGET_SOFT_FLOAT) ? GP_RETURN : (FP_REG_FIRST + 16))
+#define GP_RETURN GP_ARG_FIRST
+#define FP_RETURN ((TARGET_SOFT_FLOAT) ? GP_RETURN : FP_ARG_FIRST)
 
 #define MAX_ARGS_IN_REGISTERS 8
 
 /* Symbolic macros for the first/last argument registers.  */
 
-#define GP_ARG_FIRST (GP_REG_FIRST + 18)
+#define GP_ARG_FIRST (GP_REG_FIRST + 10)
 #define GP_ARG_LAST  (GP_ARG_FIRST + MAX_ARGS_IN_REGISTERS - 1)
-#define GP_TEMP_FIRST (GP_ARG_LAST + 1)
-#define FP_ARG_FIRST (FP_REG_FIRST + 18)
+#define GP_TEMP_FIRST (GP_REG_FIRST + 5)
+#define FP_ARG_FIRST (FP_REG_FIRST + 10)
 #define FP_ARG_LAST  (FP_ARG_FIRST + MAX_ARGS_IN_REGISTERS - 1)
 
 #define LIBCALL_VALUE(MODE) \
@@ -797,8 +727,6 @@ enum reg_class
 #define FUNCTION_VALUE(VALTYPE, FUNC) \
   riscv_function_value (VALTYPE, FUNC, VOIDmode)
 
-/* Return scalar values in v0 or fv0. */
-
 #define FUNCTION_VALUE_REGNO_P(N) ((N) == GP_RETURN || (N) == FP_RETURN)
 
 /* 1 if N is a possible register number for function argument passing.
@@ -909,6 +837,7 @@ typedef struct {
 
 #define JUMP_TABLES_IN_TEXT_SECTION 0
 #define CASE_VECTOR_MODE SImode
+#define CASE_VECTOR_PC_RELATIVE (riscv_cmodel != CM_MEDLOW)
 
 /* Define this as 1 if `char' should by default be signed; else as 0.  */
 #define DEFAULT_SIGNED_CHAR 0
@@ -939,10 +868,12 @@ typedef struct {
 
 #define FUNCTION_MODE SImode
 
-/* A C expression for the cost of a branch instruction.  A value of
-   1 is the default; other values are interpreted relative to that.  */
+/* A C expression for the cost of a branch instruction.  A value of 2
+   seems to minimize code size.  */
+
+#define BRANCH_COST(speed_p, predictable_p) \
+  ((!(speed_p) || (predictable_p)) ? 2 : riscv_branch_cost)
 
-#define BRANCH_COST(speed_p, predictable_p) riscv_branch_cost
 #define LOGICAL_OP_NON_SHORT_CIRCUIT 0
 
 /* Control the assembler format that we output.  */
@@ -962,14 +893,14 @@ typedef struct {
 #endif
 
 #define REGISTER_NAMES						\
-{ "zero","ra",  "s0",  "s1",  "s2",  "s3",  "s4",  "s5",	\
-  "s6",  "s7",  "s8",  "s9",  "s10", "s11", "sp",  "tp",	\
-  "v0",  "v1",  "a0",  "a1",  "a2",  "a3",  "a4",  "a5",	\
-  "a6",  "a7",  "t0",  "t1",  "t2",  "t3",  "t4",  "gp",	\
-  "f0",  "f1",  "f2",  "f3",  "f4",  "f5",  "f6",  "f7",	\
-  "f8",  "f9",  "f10", "f11", "f12", "f13", "f14", "f15",	\
-  "f16", "f17", "f18", "f19", "f20", "f21", "f22", "f23",	\
-  "f24", "f25", "f26", "f27", "f28", "f29", "f30", "f31",	\
+{ "zero","ra",  "sp",  "gp",  "tp",  "t0",  "t1",  "t2",	\
+  "s0",  "s1",  "a0",  "a1",  "a2",  "a3",  "a4",  "a5",	\
+  "a6",  "a7",  "s2",  "s3",  "s4",  "s5",  "s6",  "s7",	\
+  "s8",  "s9",  "s10", "s11", "t3",  "t4",  "t5",  "t6",	\
+  "ft0", "ft1", "ft2", "ft3", "ft4", "ft5", "ft6", "ft7",	\
+  "fs0", "fs1", "fa0", "fa1", "fa2", "fa3", "fa4", "fa5",	\
+  "fa6", "fa7", "fs2", "fs3", "fs4", "fs5", "fs6", "fs7",	\
+  "fs8", "fs9", "fs10","fs11","ft8", "ft9", "ft10","ft11",	\
   "arg", "frame", }
 
 #define ADDITIONAL_REGISTER_NAMES					\
@@ -1006,38 +937,38 @@ typedef struct {
   { "x29",	29 + GP_REG_FIRST },					\
   { "x30",	30 + GP_REG_FIRST },					\
   { "x31",	31 + GP_REG_FIRST },					\
-  { "fs0",	 0 + FP_REG_FIRST },					\
-  { "fs1",	 1 + FP_REG_FIRST },					\
-  { "fs2",	 2 + FP_REG_FIRST },					\
-  { "fs3",	 3 + FP_REG_FIRST },					\
-  { "fs4",	 4 + FP_REG_FIRST },					\
-  { "fs5",	 5 + FP_REG_FIRST },					\
-  { "fs6",	 6 + FP_REG_FIRST },					\
-  { "fs7",	 7 + FP_REG_FIRST },					\
-  { "fs8",	 8 + FP_REG_FIRST },					\
-  { "fs9",	 9 + FP_REG_FIRST },					\
-  { "fs10",	10 + FP_REG_FIRST },					\
-  { "fs11",	11 + FP_REG_FIRST },					\
-  { "fs12",	12 + FP_REG_FIRST },					\
-  { "fs13",	13 + FP_REG_FIRST },					\
-  { "fs14",	14 + FP_REG_FIRST },					\
-  { "fs15",	15 + FP_REG_FIRST },					\
-  { "fv0",	16 + FP_REG_FIRST },					\
-  { "fv1",	17 + FP_REG_FIRST },					\
-  { "fa0",	18 + FP_REG_FIRST },					\
-  { "fa1",	19 + FP_REG_FIRST },					\
-  { "fa2",	20 + FP_REG_FIRST },					\
-  { "fa3",	21 + FP_REG_FIRST },					\
-  { "fa4",	22 + FP_REG_FIRST },					\
-  { "fa5",	23 + FP_REG_FIRST },					\
-  { "fa6",	24 + FP_REG_FIRST },					\
-  { "fa7",	25 + FP_REG_FIRST },					\
-  { "ft0",	26 + FP_REG_FIRST },					\
-  { "ft1",	27 + FP_REG_FIRST },					\
-  { "ft2",	28 + FP_REG_FIRST },					\
-  { "ft3",	29 + FP_REG_FIRST },					\
-  { "ft4",	30 + FP_REG_FIRST },					\
-  { "ft5",	31 + FP_REG_FIRST },					\
+  { "f0",	 0 + FP_REG_FIRST },					\
+  { "f1",	 1 + FP_REG_FIRST },					\
+  { "f2",	 2 + FP_REG_FIRST },					\
+  { "f3",	 3 + FP_REG_FIRST },					\
+  { "f4",	 4 + FP_REG_FIRST },					\
+  { "f5",	 5 + FP_REG_FIRST },					\
+  { "f6",	 6 + FP_REG_FIRST },					\
+  { "f7",	 7 + FP_REG_FIRST },					\
+  { "f8",	 8 + FP_REG_FIRST },					\
+  { "f9",	 9 + FP_REG_FIRST },					\
+  { "f10",	10 + FP_REG_FIRST },					\
+  { "f11",	11 + FP_REG_FIRST },					\
+  { "f12",	12 + FP_REG_FIRST },					\
+  { "f13",	13 + FP_REG_FIRST },					\
+  { "f14",	14 + FP_REG_FIRST },					\
+  { "f15",	15 + FP_REG_FIRST },					\
+  { "f16",	16 + FP_REG_FIRST },					\
+  { "f17",	17 + FP_REG_FIRST },					\
+  { "f18",	18 + FP_REG_FIRST },					\
+  { "f19",	19 + FP_REG_FIRST },					\
+  { "f20",	20 + FP_REG_FIRST },					\
+  { "f21",	21 + FP_REG_FIRST },					\
+  { "f22",	22 + FP_REG_FIRST },					\
+  { "f23",	23 + FP_REG_FIRST },					\
+  { "f24",	24 + FP_REG_FIRST },					\
+  { "f25",	25 + FP_REG_FIRST },					\
+  { "f26",	26 + FP_REG_FIRST },					\
+  { "f27",	27 + FP_REG_FIRST },					\
+  { "f28",	28 + FP_REG_FIRST },					\
+  { "f29",	29 + FP_REG_FIRST },					\
+  { "f30",	30 + FP_REG_FIRST },					\
+  { "f31",	31 + FP_REG_FIRST },					\
 }
 
 /* Globalizing directive for a label.  */
@@ -1191,8 +1122,7 @@ while (0)
 extern const enum reg_class riscv_regno_to_class[];
 extern bool riscv_hard_regno_mode_ok[][FIRST_PSEUDO_REGISTER];
 extern const char* riscv_hi_relocs[];
-extern enum processor riscv_tune;        /* which cpu to schedule for */
 #endif
 
 #define ASM_PREFERRED_EH_DATA_FORMAT(CODE,GLOBAL) \
-  (((GLOBAL) ? DW_EH_PE_indirect : 0) | DW_EH_PE_absptr)
+  (((GLOBAL) ? DW_EH_PE_indirect : 0) | DW_EH_PE_pcrel | DW_EH_PE_sdata4)
Index: src/external/gpl3/gcc/dist/gcc/config/riscv/riscv.md
diff -u src/external/gpl3/gcc/dist/gcc/config/riscv/riscv.md:1.1 src/external/gpl3/gcc/dist/gcc/config/riscv/riscv.md:1.2
--- src/external/gpl3/gcc/dist/gcc/config/riscv/riscv.md:1.1	Fri Sep 19 17:20:29 2014
+++ src/external/gpl3/gcc/dist/gcc/config/riscv/riscv.md	Fri Mar 27 01:51:34 2015
@@ -19,10 +19,6 @@
 ;; along with GCC; see the file COPYING3.  If not see
 ;; <http://www.gnu.org/licenses/>.
 
-(define_enum "processor" [
-  rocket
-])
-
 (define_c_enum "unspec" [
   ;; Floating-point moves.
   UNSPEC_LOAD_LOW
@@ -33,13 +29,12 @@
   UNSPEC_EH_RETURN
 
   ;; Symbolic accesses.
+  UNSPEC_ADDRESS_FIRST
   UNSPEC_LOAD_GOT
-  UNSPEC_TLS_LE_ADD
-  UNSPEC_TLS_IE_ADD
-  UNSPEC_TLS_GD
+  UNSPEC_TLS
+  UNSPEC_TLS_LE
   UNSPEC_TLS_IE
-  UNSPEC_TLS_IE_HI
-  UNSPEC_TLS_IE_LO
+  UNSPEC_TLS_GD
 
   ;; Blockage and synchronisation.
   UNSPEC_BLOCKAGE
@@ -241,10 +236,6 @@
 	  (symbol_ref "riscv_load_store_insns (operands[0], insn) * 4")
 	  ] (const_int 4)))
 
-;; Attribute describing the processor.
-(define_enum_attr "cpu" "processor"
-  (const (symbol_ref "riscv_tune")))
-
 ;; Describe a user's asm statement.
 (define_asm_attributes
   [(set_attr "type" "multi")])
@@ -346,9 +337,6 @@
 ;; from the same template.
 (define_code_iterator any_mod [mod umod])
 
-;; Equality operators.
-(define_code_iterator equality_op [eq ne])
-
 ;; These code iterators allow the signed and unsigned scc operations to use
 ;; the same template.
 (define_code_iterator any_gt [gt gtu])
@@ -389,13 +377,6 @@
 			(plus "add")
 			(minus "sub")])
 
-;; The value of the bit when the branch is taken for branch_bit patterns.
-;; Comparison is always against zero so this depends on the operator.
-(define_code_attr bbv [(eq "0") (ne "1")])
-
-;; This is the inverse value of bbv.
-(define_code_attr bbinv [(eq "1") (ne "0")])
-
 ;; Pipeline descriptions.
 ;;
 ;; generic.md provides a fallback for processors without a specific
@@ -607,13 +588,13 @@
   [(set (match_operand:GPR 0 "register_operand")
 	(mult:GPR (match_operand:GPR 1 "reg_or_0_operand")
 		   (match_operand:GPR 2 "register_operand")))]
-  "")
+  "TARGET_MULDIV")
 
 (define_insn "*mulsi3"
   [(set (match_operand:SI 0 "register_operand" "=r")
 	(mult:SI (match_operand:GPR 1 "register_operand" "r")
 		  (match_operand:GPR2 2 "register_operand" "r")))]
-  ""
+  "TARGET_MULDIV"
   { return TARGET_64BIT ? "mulw\t%0,%1,%2" : "mul\t%0,%1,%2"; }
   [(set_attr "type" "imul")
    (set_attr "mode" "SI")])
@@ -622,7 +603,7 @@
   [(set (match_operand:SI 0 "register_operand" "=r")
 	     (mult:SI (truncate:SI (match_operand:DI 1 "register_operand" "r"))
 		      (truncate:SI (match_operand:DI 2 "register_operand" "r"))))]
-  "TARGET_64BIT"
+  "TARGET_MULDIV && TARGET_64BIT"
   "mulw\t%0,%1,%2"
   [(set_attr "type" "imul")
    (set_attr "mode" "SI")])
@@ -632,7 +613,7 @@
           (truncate:SI
 	     (mult:DI (match_operand:DI 1 "register_operand" "r")
 		      (match_operand:DI 2 "register_operand" "r"))))]
-  "TARGET_64BIT"
+  "TARGET_MULDIV && TARGET_64BIT"
   "mulw\t%0,%1,%2"
   [(set_attr "type" "imul")
    (set_attr "mode" "SI")])
@@ -641,7 +622,7 @@
   [(set (match_operand:DI 0 "register_operand" "=r")
 	(mult:DI (match_operand:DI 1 "register_operand" "r")
 		  (match_operand:DI 2 "register_operand" "r")))]
-  "TARGET_64BIT"
+  "TARGET_MULDIV && TARGET_64BIT"
   "mul\t%0,%1,%2"
   [(set_attr "type" "imul")
    (set_attr "mode" "DI")])
@@ -663,7 +644,7 @@
 		 (any_extend:TI
 		   (match_operand:DI 2 "register_operand" "r"))))
   (clobber (match_scratch:DI 3 "=r"))]
-  "TARGET_64BIT"
+  "TARGET_MULDIV && TARGET_64BIT"
   "#"
   "reload_completed"
   [
@@ -690,7 +671,7 @@
 		     (any_extend:TI
 		       (match_operand:DI 2 "register_operand" "r")))
 	    (const_int 64))))]
-  "TARGET_64BIT"
+  "TARGET_MULDIV && TARGET_64BIT"
   "mulh<u>\t%0,%1,%2"
   [(set_attr "type" "imul")
    (set_attr "mode" "DI")])
@@ -703,7 +684,7 @@
 		 (sign_extend:TI
 		   (match_operand:DI 2 "register_operand" "r"))))
   (clobber (match_scratch:DI 3 "=r"))]
-  "TARGET_64BIT"
+  "TARGET_MULDIV && TARGET_64BIT"
   "#"
   "reload_completed"
   [
@@ -730,33 +711,26 @@
 		     (sign_extend:TI
 		       (match_operand:DI 2 "register_operand" "r")))
 	    (const_int 64))))]
-  "TARGET_64BIT"
+  "TARGET_MULDIV && TARGET_64BIT"
   "mulhsu\t%0,%2,%1"
   [(set_attr "type" "imul")
    (set_attr "mode" "DI")])
 
-(define_insn_and_split "<u>mulsidi3"
+(define_expand "<u>mulsidi3"
   [(set (match_operand:DI 0 "register_operand" "=r")
 	(mult:DI (any_extend:DI
 		   (match_operand:SI 1 "register_operand" "r"))
 		 (any_extend:DI
 		   (match_operand:SI 2 "register_operand" "r"))))
   (clobber (match_scratch:SI 3 "=r"))]
-  "!TARGET_64BIT"
-  "#"
-  "reload_completed"
-  [
-   (set (match_dup 3) (mult:SI (match_dup 1) (match_dup 2)))
-   (set (match_dup 4) (truncate:SI
-			(lshiftrt:DI
-			  (mult:DI (any_extend:DI (match_dup 1))
-				   (any_extend:DI (match_dup 2)))
-			  (const_int 32))))
-   (set (match_dup 5) (match_dup 3))
-  ]
+  "TARGET_MULDIV && !TARGET_64BIT"
 {
-  operands[4] = riscv_subword (operands[0], true);
-  operands[5] = riscv_subword (operands[0], false);
+  rtx temp = gen_reg_rtx (SImode);
+  emit_insn (gen_mulsi3 (temp, operands[1], operands[2]));
+  emit_insn (gen_<u>mulsi3_highpart (riscv_subword (operands[0], true),
+				     operands[1], operands[2]));
+  emit_insn (gen_movsi (riscv_subword (operands[0], false), temp));
+  DONE;
 }
   )
 
@@ -769,34 +743,27 @@
 		     (any_extend:DI
 		       (match_operand:SI 2 "register_operand" "r")))
 	    (const_int 32))))]
-  "!TARGET_64BIT"
+  "TARGET_MULDIV && !TARGET_64BIT"
   "mulh<u>\t%0,%1,%2"
   [(set_attr "type" "imul")
    (set_attr "mode" "SI")])
 
 
-(define_insn_and_split "usmulsidi3"
+(define_expand "usmulsidi3"
   [(set (match_operand:DI 0 "register_operand" "=r")
 	(mult:DI (zero_extend:DI
 		   (match_operand:SI 1 "register_operand" "r"))
 		 (sign_extend:DI
 		   (match_operand:SI 2 "register_operand" "r"))))
   (clobber (match_scratch:SI 3 "=r"))]
-  "!TARGET_64BIT"
-  "#"
-  "reload_completed"
-  [
-   (set (match_dup 3) (mult:SI (match_dup 1) (match_dup 2)))
-   (set (match_dup 4) (truncate:SI
-			(lshiftrt:DI
-			  (mult:DI (zero_extend:DI (match_dup 1))
-				   (sign_extend:DI (match_dup 2)))
-			  (const_int 32))))
-   (set (match_dup 5) (match_dup 3))
-  ]
+  "TARGET_MULDIV && !TARGET_64BIT"
 {
-  operands[4] = riscv_subword (operands[0], true);
-  operands[5] = riscv_subword (operands[0], false);
+  rtx temp = gen_reg_rtx (SImode);
+  emit_insn (gen_mulsi3 (temp, operands[1], operands[2]));
+  emit_insn (gen_usmulsi3_highpart (riscv_subword (operands[0], true),
+				     operands[1], operands[2]));
+  emit_insn (gen_movsi (riscv_subword (operands[0], false), temp));
+  DONE;
 }
   )
 
@@ -809,7 +776,7 @@
 		     (sign_extend:DI
 		       (match_operand:SI 2 "register_operand" "r")))
 	    (const_int 32))))]
-  "!TARGET_64BIT"
+  "TARGET_MULDIV && !TARGET_64BIT"
   "mulhsu\t%0,%2,%1"
   [(set_attr "type" "imul")
    (set_attr "mode" "SI")])
@@ -826,7 +793,7 @@
   [(set (match_operand:SI 0 "register_operand" "=r")
 	(any_div:SI (match_operand:SI 1 "register_operand" "r")
 		  (match_operand:SI 2 "register_operand" "r")))]
-  ""
+  "TARGET_MULDIV"
   { return TARGET_64BIT ? "div<u>w\t%0,%1,%2" : "div<u>\t%0,%1,%2"; }
   [(set_attr "type" "idiv")
    (set_attr "mode" "SI")])
@@ -835,7 +802,7 @@
   [(set (match_operand:DI 0 "register_operand" "=r")
 	(any_div:DI (match_operand:DI 1 "register_operand" "r")
 		  (match_operand:DI 2 "register_operand" "r")))]
-  "TARGET_64BIT"
+  "TARGET_MULDIV && TARGET_64BIT"
   "div<u>\t%0,%1,%2"
   [(set_attr "type" "idiv")
    (set_attr "mode" "DI")])
@@ -844,7 +811,7 @@
   [(set (match_operand:SI 0 "register_operand" "=r")
 	(any_mod:SI (match_operand:SI 1 "register_operand" "r")
 		  (match_operand:SI 2 "register_operand" "r")))]
-  ""
+  "TARGET_MULDIV"
   { return TARGET_64BIT ? "rem<u>w\t%0,%1,%2" : "rem<u>\t%0,%1,%2"; }
   [(set_attr "type" "idiv")
    (set_attr "mode" "SI")])
@@ -853,7 +820,7 @@
   [(set (match_operand:DI 0 "register_operand" "=r")
 	(any_mod:DI (match_operand:DI 1 "register_operand" "r")
 		  (match_operand:DI 2 "register_operand" "r")))]
-  "TARGET_64BIT"
+  "TARGET_MULDIV && TARGET_64BIT"
   "rem<u>\t%0,%1,%2"
   [(set_attr "type" "idiv")
    (set_attr "mode" "DI")])
@@ -1210,16 +1177,20 @@
 ;; the register alternative needs a reload.
 (define_insn_and_split "extendsidi2"
   [(set (match_operand:DI 0 "register_operand" "=r,r")
-        (sign_extend:DI (match_operand:SI 1 "nonimmediate_operand" "0,m")))]
+        (sign_extend:DI (match_operand:SI 1 "nonimmediate_operand" "r,m")))]
   "TARGET_64BIT"
   "@
    #
    lw\t%0,%1"
   "&& reload_completed && register_operand (operands[1], VOIDmode)"
-  [(const_int 0)]
+  [(set (match_dup 0) (match_dup 1))]
 {
-  emit_note (NOTE_INSN_DELETED);
-  DONE;
+  if (REGNO (operands[0]) == REGNO (operands[1]))
+    {
+      emit_note (NOTE_INSN_DELETED);
+      DONE;
+    }
+  operands[1] = gen_rtx_REG (DImode, REGNO (operands[1]));
 }
   [(set_attr "move_type" "move,load")
    (set_attr "mode" "DI")])
@@ -1444,23 +1415,12 @@
 	(unspec:P [(match_operand:P 1 "register_operand" "r")
 		   (match_operand:P 2 "register_operand" "r")
 		   (match_operand:P 3 "symbolic_operand" "")]
-		  UNSPEC_TLS_LE_ADD))]
-  "!flag_pic"
+		  UNSPEC_TLS_LE))]
+  "!flag_pic || flag_pie"
   "add\t%0,%1,%2,%%tprel_add(%3)"
   [(set_attr "type" "arith")
    (set_attr "mode" "<MODE>")])
 
-(define_insn "tls_add_tp_ie<mode>"
-  [(set (match_operand:P 0 "register_operand" "=r")
-	(unspec:P [(match_operand:P 1 "register_operand" "r")
-		   (match_operand:P 2 "register_operand" "r")
-		   (match_operand:P 3 "symbolic_operand" "")]
-		  UNSPEC_TLS_IE_ADD))]
-  "!flag_pic"
-  "add\t%0,%1,%2,%%tls_ie_add(%3)"
-  [(set_attr "type" "arith")
-   (set_attr "mode" "<MODE>")])
-
 (define_insn "got_load_tls_gd<mode>"
   [(set (match_operand:P 0 "register_operand" "=r")
        (unspec:P [(match_operand:P 1 "symbolic_operand" "")]
@@ -1479,25 +1439,6 @@
   [(set_attr "got" "load")
    (set_attr "mode" "<MODE>")])
 
-(define_insn "got_load_tls_ie_hi<mode>"
-  [(set (match_operand:P 0 "register_operand" "=r")
-       (unspec:P [(match_operand:P 1 "symbolic_operand" "")]
-                 UNSPEC_TLS_IE_HI))]
-  "!flag_pic"
-  "lui\t%0,%%tls_ie_hi(%1)"
-  [(set_attr "type" "arith")
-   (set_attr "mode" "<MODE>")])
-
-(define_insn "got_load_tls_ie_lo<mode>"
-  [(set (match_operand:P 0 "register_operand" "=r")
-	(unspec:P [(match_operand:P 1 "register_operand" "r")
-		   (match_operand:P 2 "symbolic_operand" "")]
-		  UNSPEC_TLS_IE_LO))]
-  "!flag_pic"
-  "<load>\t%0,%%tls_ie_lo(%2)(%1)"
-  [(set_attr "type" "load")
-   (set_attr "mode" "<MODE>")])
-
 ;; Instructions for adding the low 16 bits of an address to a register.
 ;; Operand 2 is the address: riscv_print_operand works out which relocation
 ;; should be applied.
@@ -1615,12 +1556,12 @@
 })
 
 (define_insn "*movhi_internal"
-  [(set (match_operand:HI 0 "nonimmediate_operand" "=r,r,r,m")
-	(match_operand:HI 1 "move_operand"         "r,T,m,rJ"))]
+  [(set (match_operand:HI 0 "nonimmediate_operand" "=r,r,r,m,*f,*r")
+	(match_operand:HI 1 "move_operand"         "r,T,m,rJ,*r*J,*f"))]
   "(register_operand (operands[0], HImode)
     || reg_or_0_operand (operands[1], HImode))"
   { return riscv_output_move (operands[0], operands[1]); }
-  [(set_attr "move_type" "move,const,load,store")
+  [(set_attr "move_type" "move,const,load,store,mtc,mfc")
    (set_attr "mode" "HI")])
 
 ;; HImode constant generation; see riscv_move_integer for details.
@@ -1656,12 +1597,12 @@
 })
 
 (define_insn "*movqi_internal"
-  [(set (match_operand:QI 0 "nonimmediate_operand" "=r,r,r,m")
-	(match_operand:QI 1 "move_operand"         "r,I,m,rJ"))]
+  [(set (match_operand:QI 0 "nonimmediate_operand" "=r,r,r,m,*f,*r")
+	(match_operand:QI 1 "move_operand"         "r,I,m,rJ,*r*J,*f"))]
   "(register_operand (operands[0], QImode)
     || reg_or_0_operand (operands[1], QImode))"
   { return riscv_output_move (operands[0], operands[1]); }
-  [(set_attr "move_type" "move,const,load,store")
+  [(set_attr "move_type" "move,const,load,store,mtc,mfc")
    (set_attr "mode" "QI")])
 
 ;; 32-bit floating point moves
@@ -1847,7 +1788,7 @@
   ""
   "fence.i")
 
-;; Block moves, see mips.c for more details.
+;; Block moves, see riscv.c for more details.
 ;; Argument 0 is the destination
 ;; Argument 1 is the source
 ;; Argument 2 is the length
@@ -1901,8 +1842,8 @@
   [(set (match_operand:SI 0 "register_operand" "=r")
           (truncate:SI
 	     (ashift:DI (match_operand:DI 1 "register_operand" "r")
-		      (match_operand:DI 2 "arith_operand" "rI"))))]
-  "TARGET_64BIT && (GET_CODE (operands[2]) == CONST_INT ? INTVAL (operands[2]) < 32 : 1)"
+		      (match_operand:DI 2 "const_arith_operand" "I"))))]
+  "TARGET_64BIT && INTVAL (operands[2]) < 32"
   "sllw\t%0,%1,%2"
   [(set_attr "type" "shift")
    (set_attr "mode" "SI")])
@@ -2001,6 +1942,62 @@
   DONE;
 })
 
+(define_insn_and_split "*branch_on_bit<GPR:mode>"
+  [(set (pc)
+	(if_then_else
+	 (match_operator 0 "equality_operator"
+	  [(zero_extract:GPR (match_operand:GPR 2 "register_operand" "r")
+		 (const_int 1)
+		 (match_operand 3 "const_int_operand"))
+		 (const_int 0)])
+	 (label_ref (match_operand 1))
+	 (pc)))
+   (clobber (match_scratch:GPR 4 "=&r"))]
+  ""
+  "#"
+  "reload_completed"
+  [(set (match_dup 4)
+        (ashift:GPR (match_dup 2) (match_dup 3)))
+   (set (pc)
+	(if_then_else
+	 (match_op_dup 0 [(match_dup 4) (const_int 0)])
+	 (label_ref (match_operand 1))
+	 (pc)))]
+{
+  int shift = GET_MODE_BITSIZE (<MODE>mode) - 1 - INTVAL (operands[3]);
+  operands[3] = GEN_INT (shift);
+
+  if (GET_CODE (operands[0]) == EQ)
+    operands[0] = gen_rtx_GE (<MODE>mode, operands[4], const0_rtx);
+  else
+    operands[0] = gen_rtx_LT (<MODE>mode, operands[4], const0_rtx);
+})
+
+(define_insn_and_split "*branch_on_bit_range<GPR:mode>"
+  [(set (pc)
+	(if_then_else
+	 (match_operator 0 "equality_operator"
+	  [(zero_extract:GPR (match_operand:GPR 2 "register_operand" "r")
+		 (match_operand 3 "const_int_operand")
+		 (const_int 0))
+		 (const_int 0)])
+	 (label_ref (match_operand 1))
+	 (pc)))
+   (clobber (match_scratch:GPR 4 "=&r"))]
+  ""
+  "#"
+  "reload_completed"
+  [(set (match_dup 4)
+        (ashift:GPR (match_dup 2) (match_dup 3)))
+   (set (pc)
+	(if_then_else
+	 (match_op_dup 0 [(match_dup 4) (const_int 0)])
+	 (label_ref (match_operand 1))
+	 (pc)))]
+{
+  operands[3] = GEN_INT (GET_MODE_BITSIZE (<MODE>mode) - INTVAL (operands[3]));
+})
+
 ;;
 ;;  ....................
 ;;
@@ -2129,12 +2126,12 @@
 	      (use (label_ref (match_operand 1 "" "")))]
   ""
 {
-  if (flag_pic)
+  if (CASE_VECTOR_PC_RELATIVE)
       operands[0] = expand_simple_binop (Pmode, PLUS, operands[0],
 					 gen_rtx_LABEL_REF (Pmode, operands[1]),
 					 NULL_RTX, 0, OPTAB_DIRECT);
 
-  if (flag_pic && Pmode == DImode)
+  if (CASE_VECTOR_PC_RELATIVE && Pmode == DImode)
     emit_jump_insn (gen_tablejumpdi (operands[0], operands[1]));
   else
     emit_jump_insn (gen_tablejumpsi (operands[0], operands[1]));
@@ -2195,17 +2192,22 @@
 ;; Trivial return.  Make it look like a normal return insn as that
 ;; allows jump optimizations to work better.
 
-(define_insn "return"
-  [(return)]
+(define_expand "return"
+  [(simple_return)]
   "riscv_can_use_return_insn ()"
+  "")
+
+(define_insn "simple_return"
+  [(simple_return)]
+  ""
   "ret"
   [(set_attr "type"	"jump")
    (set_attr "mode"	"none")])
 
 ;; Normal return.
 
-(define_insn "return_internal"
-  [(return)
+(define_insn "simple_return_internal"
+  [(simple_return)
    (use (match_operand 0 "pmode_register_operand" ""))]
   ""
   "jr\t%0"
@@ -2284,8 +2286,8 @@
 	 (match_operand 1 "" ""))]
   "SIBLING_CALL_P (insn)"
   { return REG_P (operands[0]) ? "jr\t%0"
-	   : absolute_symbolic_operand (operands[0], VOIDmode) ? "jump\t%0"
-	   : "jump\t%0@"; }
+	   : absolute_symbolic_operand (operands[0], VOIDmode) ? "tail\t%0"
+	   : "tail\t%0@"; }
   [(set_attr "type" "call")])
 
 (define_expand "sibcall_value"
@@ -2305,8 +2307,8 @@
               (match_operand 2 "" "")))]
   "SIBLING_CALL_P (insn)"
   { return REG_P (operands[1]) ? "jr\t%1"
-	   : absolute_symbolic_operand (operands[1], VOIDmode) ? "jump\t%1"
-	   : "jump\t%1@"; }
+	   : absolute_symbolic_operand (operands[1], VOIDmode) ? "tail\t%1"
+	   : "tail\t%1@"; }
   [(set_attr "type" "call")])
 
 (define_insn "sibcall_value_multiple_internal"
@@ -2319,8 +2321,8 @@
    (clobber (match_scratch:SI 4 "=j,j"))]
   "SIBLING_CALL_P (insn)"
   { return REG_P (operands[1]) ? "jr\t%1"
-	   : absolute_symbolic_operand (operands[1], VOIDmode) ? "jump\t%1"
-	   : "jump\t%1@"; }
+	   : absolute_symbolic_operand (operands[1], VOIDmode) ? "tail\t%1"
+	   : "tail\t%1@"; }
   [(set_attr "type" "call")])
 
 (define_expand "call"
@@ -2419,7 +2421,3 @@
 
 (include "sync.md")
 (include "peephole.md")
-
-(define_c_enum "unspec" [
-  UNSPEC_ADDRESS_FIRST
-])
Index: src/external/gpl3/gcc/dist/gcc/config/riscv/riscv.opt
diff -u src/external/gpl3/gcc/dist/gcc/config/riscv/riscv.opt:1.1 src/external/gpl3/gcc/dist/gcc/config/riscv/riscv.opt:1.2
--- src/external/gpl3/gcc/dist/gcc/config/riscv/riscv.opt:1.1	Fri Sep 19 17:20:29 2014
+++ src/external/gpl3/gcc/dist/gcc/config/riscv/riscv.opt	Fri Mar 27 01:51:34 2015
@@ -50,6 +50,10 @@ mfdiv
 Target Report RejectNegative Mask(FDIV)
 Use hardware floating-point divide and square root instructions
 
+march=
+Target RejectNegative Joined Var(riscv_arch_string)
+-march=			Generate code for given RISC-V ISA (e.g. RV64IM)
+
 mtune=
 Target RejectNegative Joined Var(riscv_tune_string)
 -mtune=PROCESSOR	Optimize the output for PROCESSOR
@@ -60,4 +64,16 @@ Target Joined Separate UInteger Var(g_sw
 
 matomic
 Target Report Mask(ATOMIC)
-Use hardware atomic memory instructions.  Enabled by default, use -mno-atomic to disable
+Use hardware atomic memory instructions.
+
+mmuldiv
+Target Report Mask(MULDIV)
+Use hardware instructions for integer multiplication and division.
+
+mlra
+Target Report Var(riscv_lra_flag) Init(0) Save
+Use LRA instead of reload
+
+mcmodel=
+Target RejectNegative Joined Var(riscv_cmodel_string)
+Use given RISC-V code model (medlow or medany)
Index: src/external/gpl3/gcc/dist/gcc/config/riscv/t-elf
diff -u src/external/gpl3/gcc/dist/gcc/config/riscv/t-elf:1.1 src/external/gpl3/gcc/dist/gcc/config/riscv/t-elf:1.2
--- src/external/gpl3/gcc/dist/gcc/config/riscv/t-elf:1.1	Fri Sep 19 17:20:29 2014
+++ src/external/gpl3/gcc/dist/gcc/config/riscv/t-elf	Fri Mar 27 01:51:34 2015
@@ -1,5 +1,4 @@
 # Build the libraries for both hard and soft floating point
 
-MULTILIB_OPTIONS = msoft-float m64/m32 mfdiv mno-atomic
-MULTILIB_DIRNAMES = soft-float 64 32 fdiv no-atomic
-MULTILIB_EXCEPTIONS = *msoft-float*/*mfdiv*
+MULTILIB_OPTIONS = msoft-float m64/m32 mno-atomic
+MULTILIB_DIRNAMES = soft-float 64 32 no-atomic
Index: src/external/gpl3/gcc/dist/gcc/config/riscv/t-linux64
diff -u src/external/gpl3/gcc/dist/gcc/config/riscv/t-linux64:1.1 src/external/gpl3/gcc/dist/gcc/config/riscv/t-linux64:1.2
--- src/external/gpl3/gcc/dist/gcc/config/riscv/t-linux64:1.1	Fri Sep 19 17:20:29 2014
+++ src/external/gpl3/gcc/dist/gcc/config/riscv/t-linux64	Fri Mar 27 01:51:34 2015
@@ -1,6 +1,5 @@
 # Build the libraries for both hard and soft floating point
 
-MULTILIB_OPTIONS = m64/m32 msoft-float mfdiv mno-atomic
-MULTILIB_DIRNAMES = 64 32 soft-float fdiv no-atomic
-MULTILIB_EXCEPTIONS = *msoft-float*/*mfdiv*
+MULTILIB_OPTIONS = m64/m32 msoft-float mno-atomic
+MULTILIB_DIRNAMES = 64 32 soft-float no-atomic
 MULTILIB_OSDIRNAMES = ../lib ../lib32

Index: src/external/gpl3/gcc/dist/gcc/config/riscv/sync.md
diff -u src/external/gpl3/gcc/dist/gcc/config/riscv/sync.md:1.2 src/external/gpl3/gcc/dist/gcc/config/riscv/sync.md:1.3
--- src/external/gpl3/gcc/dist/gcc/config/riscv/sync.md:1.2	Mon Dec 22 21:15:48 2014
+++ src/external/gpl3/gcc/dist/gcc/config/riscv/sync.md	Fri Mar 27 01:51:34 2015
@@ -71,7 +71,7 @@
 
 ;; Implement atomic stores with amoswap.  Fall back to fences for atomic loads.
 (define_insn "atomic_store<mode>"
-  [(set (match_operand:GPR 0 "memory_operand" "=YR")
+  [(set (match_operand:GPR 0 "memory_operand" "=A")
     (unspec_volatile:GPR
       [(match_operand:GPR 1 "reg_or_0_operand" "rJ")
        (match_operand:SI 2 "const_int_operand")]      ;; model
@@ -79,18 +79,19 @@
   "TARGET_ATOMIC"
   "amoswap.<amo>%A2 zero,%z1,%0")
 
-(define_insn "sync_<optab><mode>"
-  [(set (match_operand:GPR 0 "memory_operand" "+YR")
+(define_insn "atomic_<atomic_optab><mode>"
+  [(set (match_operand:GPR 0 "memory_operand" "+A")
 	(unspec_volatile:GPR
 	  [(any_atomic:GPR (match_dup 0)
-	   (match_operand:GPR 1 "reg_or_0_operand" "rJ"))]
-	  UNSPEC_SYNC_OLD_OP))]
+		     (match_operand:GPR 1 "reg_or_0_operand" "rJ"))
+	   (match_operand:SI 2 "const_int_operand")] ;; model
+	 UNSPEC_SYNC_OLD_OP))]
   "TARGET_ATOMIC"
-  "amo<insn>.<amo>.sc zero,%z1,%0")
+  "amo<insn>.<amo>%A2 zero,%z1,%0")
 
 (define_insn "atomic_fetch_<atomic_optab><mode>"
   [(set (match_operand:GPR 0 "register_operand" "=&r")
-	(match_operand:GPR 1 "memory_operand" "+YR"))
+	(match_operand:GPR 1 "memory_operand" "+A"))
    (set (match_dup 1)
 	(unspec_volatile:GPR
 	  [(any_atomic:GPR (match_dup 1)
@@ -103,7 +104,7 @@
 (define_insn "atomic_exchange<mode>"
   [(set (match_operand:GPR 0 "register_operand" "=&r")
 	(unspec_volatile:GPR
-	  [(match_operand:GPR 1 "memory_operand" "+YR")
+	  [(match_operand:GPR 1 "memory_operand" "+A")
 	   (match_operand:SI 3 "const_int_operand")] ;; model
 	  UNSPEC_SYNC_EXCHANGE))
    (set (match_dup 1)
@@ -113,7 +114,7 @@
 
 (define_insn "atomic_cas_value_strong<mode>"
   [(set (match_operand:GPR 0 "register_operand" "=&r")
-	(match_operand:GPR 1 "memory_operand" "+YR"))
+	(match_operand:GPR 1 "memory_operand" "+A"))
    (set (match_dup 1)
 	(unspec_volatile:GPR [(match_operand:GPR 2 "reg_or_0_operand" "rJ")
 			      (match_operand:GPR 3 "reg_or_0_operand" "rJ")
@@ -157,7 +158,7 @@
 
 (define_expand "atomic_test_and_set"
   [(match_operand:QI 0 "register_operand" "")     ;; bool output
-   (match_operand:QI 1 "memory_operand" "+YR")    ;; memory
+   (match_operand:QI 1 "memory_operand" "+A")    ;; memory
    (match_operand:SI 2 "const_int_operand" "")]   ;; model
   "TARGET_ATOMIC"
 {

Added files:

Index: src/external/gpl3/gcc/dist/gcc/config/riscv/default-32.h
diff -u /dev/null src/external/gpl3/gcc/dist/gcc/config/riscv/default-32.h:1.1
--- /dev/null	Fri Mar 27 01:51:34 2015
+++ src/external/gpl3/gcc/dist/gcc/config/riscv/default-32.h	Fri Mar 27 01:51:34 2015
@@ -0,0 +1,22 @@
+/* Definitions of target machine for GCC, for RISC-V,
+   defaulting to 32-bit code generation.
+
+   Copyright (C) 1999-2014 Free Software Foundation, Inc.
+
+This file is part of GCC.
+
+GCC is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 3, or (at your option)
+any later version.
+
+GCC is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GCC; see the file COPYING3.  If not see
+<http://www.gnu.org/licenses/>.  */
+
+#define TARGET_64BIT_DEFAULT 0

Reply via email to