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