diff --git a/gcc/ChangeLog b/gcc/ChangeLog index 3913f1b37fc6..7f4b00ba16b5 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,37 @@ +2017-08-03 Kito Cheng + Monk Chiang + + * common/config/riscv/riscv-common.c (riscv_parse_arch_string): + Support parsing rv32e*. + * config.gcc (riscv*-*-elf*): Support rv32e*. + * config/riscv/riscv-c.c (riscv_cpu_cpp_builtins): Define + __riscv_32e for rv32e*. + * config/riscv/riscv.c (riscv_compute_frame_info): Support rv32e. + (riscv_conditional_register_usage): Ditto. + * config/riscv/riscv.h (BIGGEST_ALIGNMENT): Ditto. + (GP_REG_LAST): Ditto. + (STACK_BOUNDARY): Ditto. + (MAX_ARGS_IN_REGISTERS): Ditto. + (RISCV_STACK_ALIGN): Ditto. + * config/riscv/riscv.opt (RVE): Add RVE mask. + +2017-05-18 Andrew Waterman + + * config/riscv/riscv.c (riscv_option_override): Conditionally set + TARGET_STRICT_ALIGN based upon -mtune argument. + +2017-05-12 Kito Cheng + + * config/riscv/riscv.c (riscv_legitimize_move): Handle + non-legitimate address. + +2017-05-09 Palmer Dabbelt + + * config/riscv/riscv.md (ZERO_EXTEND_LOAD): Define. + * config/riscv/pic.md (local_pic_load): Rename to local_pic_load_s, + mark as a sign-extending load. + (local_pic_load_u): Define. + 2017-07-31 Segher Boessenkool * config/rs6000/rs6000.c (enum rs6000_reg_type): Delete trailing comma. diff --git a/gcc/common/config/riscv/riscv-common.c b/gcc/common/config/riscv/riscv-common.c index 50f1485f87a4..e103ab431c35 100644 --- a/gcc/common/config/riscv/riscv-common.c +++ b/gcc/common/config/riscv/riscv-common.c @@ -52,6 +52,11 @@ riscv_parse_arch_string (const char *isa, int *flags, location_t loc) *flags |= MASK_ATOMIC; *flags |= MASK_HARD_FLOAT; *flags |= MASK_DOUBLE_FLOAT; + if (*p == 'q') + { + *flags |= MASK_QUAD_FLOAT; + p++; + } } else if (*p == 'i') { @@ -74,9 +79,34 @@ riscv_parse_arch_string (const char *isa, int *flags, location_t loc) { *flags |= MASK_DOUBLE_FLOAT; p++; + if (*p == 'q') + { + *flags |= MASK_QUAD_FLOAT; + p++; + } } } } + else if (*p == 'e') + { + p++; + + *flags |= MASK_RVE; + + if (*flags & MASK_64BIT) + { + error ("RV64E is not a valid base ISA"); + return; + } + + *flags &= ~MASK_MUL; + if (*p == 'm') + *flags |= MASK_MUL, p++; + + *flags &= ~MASK_ATOMIC; + if (*p == 'a') + *flags |= MASK_ATOMIC, p++; + } else { error_at (loc, "-march=%s: invalid ISA string", isa); diff --git a/gcc/config.gcc b/gcc/config.gcc index fdf4cb845ae1..a28cdf48605b 100644 --- a/gcc/config.gcc +++ b/gcc/config.gcc @@ -4016,7 +4016,7 @@ case "${target}" in # Infer arch from --with-arch, --target, and --with-abi. case "${with_arch}" in - rv32i* | rv32g* | rv64i* | rv64g*) + rv32e* | rv32i* | rv32g* | rv64i* | rv64g*) # OK. ;; "") @@ -4024,11 +4024,12 @@ case "${target}" in case "${with_abi}" in ilp32 | ilp32f | ilp32d) with_arch="rv32gc" ;; lp64 | lp64f | lp64d) with_arch="rv64gc" ;; + lp64q) with_arch="rv64gqc" ;; *) with_arch="rv${xlen}gc" ;; esac ;; *) - echo "--with-arch=${with_arch} is not supported. The argument must begin with rv32i, rv32g, rv64i, or rv64g." 1>&2 + echo "--with-arch=${with_arch} is not supported. The argument must begin with rv32e, rv32i, rv32g, rv64i, or rv64g." 1>&2 exit 1 ;; esac @@ -4037,12 +4038,13 @@ case "${target}" in # pick a default based on the ISA, preferring soft-float # unless the D extension is present. case "${with_abi}" in - ilp32 | ilp32f | ilp32d | lp64 | lp64f | lp64d) + ilp32 | ilp32f | ilp32d | lp64 | lp64f | lp64d | lp64q) ;; "") case "${with_arch}" in rv32*d* | rv32g*) with_abi=ilp32d ;; rv32*) with_abi=ilp32 ;; + rv64*q* ) with_abi=lp64q ;; rv64*d* | rv64g*) with_abi=lp64d ;; rv64*) with_abi=lp64 ;; esac @@ -4060,7 +4062,8 @@ case "${target}" in | ilp32d,rv32*d* | ilp32d,rv32g* \ | lp64,rv64* \ | lp64f,rv64*f* | lp64f,rv64g* \ - | lp64d,rv64*d* | lp64d,rv64g*) + | lp64d,rv64*d* | lp64d,rv64g* \ + | lp64q,rv64*q* ) ;; *) echo "--with-abi=${with_abi} is not supported for ISA ${with_arch}" 1>&2 diff --git a/gcc/config/riscv/pic.md b/gcc/config/riscv/pic.md index 6a29ead32d36..03b8f9bc669e 100644 --- a/gcc/config/riscv/pic.md +++ b/gcc/config/riscv/pic.md @@ -22,13 +22,20 @@ ;; Simplify PIC loads to static variables. ;; These should go away once we figure out how to emit auipc discretely. -(define_insn "*local_pic_load" +(define_insn "*local_pic_load_s" [(set (match_operand:ANYI 0 "register_operand" "=r") - (mem:ANYI (match_operand 1 "absolute_symbolic_operand" "")))] + (sign_extend:ANYI (mem:ANYI (match_operand 1 "absolute_symbolic_operand" ""))))] "USE_LOAD_ADDRESS_MACRO (operands[1])" "\t%0,%1" [(set (attr "length") (const_int 8))]) +(define_insn "*local_pic_load_u" + [(set (match_operand:ZERO_EXTEND_LOAD 0 "register_operand" "=r") + (zero_extend:ZERO_EXTEND_LOAD (mem:ZERO_EXTEND_LOAD (match_operand 1 "absolute_symbolic_operand" ""))))] + "USE_LOAD_ADDRESS_MACRO (operands[1])" + "u\t%0,%1" + [(set (attr "length") (const_int 8))]) + (define_insn "*local_pic_load" [(set (match_operand:ANYF 0 "register_operand" "=f") (mem:ANYF (match_operand 1 "absolute_symbolic_operand" ""))) diff --git a/gcc/config/riscv/riscv-c.c b/gcc/config/riscv/riscv-c.c index 64e7cf877afe..5fe685c21639 100644 --- a/gcc/config/riscv/riscv-c.c +++ b/gcc/config/riscv/riscv-c.c @@ -37,6 +37,9 @@ riscv_cpu_cpp_builtins (cpp_reader *pfile) if (TARGET_RVC) builtin_define ("__riscv_compressed"); + if (TARGET_RVE) + builtin_define ("__riscv_32e"); + if (TARGET_ATOMIC) builtin_define ("__riscv_atomic"); @@ -73,6 +76,10 @@ riscv_cpu_cpp_builtins (cpp_reader *pfile) case ABI_LP64D: builtin_define ("__riscv_float_abi_double"); break; + + case ABI_LP64Q: + builtin_define ("__riscv_float_abi_quad"); + break; } switch (riscv_cmodel) diff --git a/gcc/config/riscv/riscv-opts.h b/gcc/config/riscv/riscv-opts.h index 2b19233379c0..e9cfc4dc2fca 100644 --- a/gcc/config/riscv/riscv-opts.h +++ b/gcc/config/riscv/riscv-opts.h @@ -27,7 +27,8 @@ enum riscv_abi_type { ABI_ILP32D, ABI_LP64, ABI_LP64F, - ABI_LP64D + ABI_LP64D, + ABI_LP64Q }; extern enum riscv_abi_type riscv_abi; diff --git a/gcc/config/riscv/riscv-protos.h b/gcc/config/riscv/riscv-protos.h index aa57d1a71529..db52eec13af0 100644 --- a/gcc/config/riscv/riscv-protos.h +++ b/gcc/config/riscv/riscv-protos.h @@ -51,7 +51,7 @@ extern rtx riscv_unspec_address (rtx, enum riscv_symbol_type); extern void riscv_move_integer (rtx, rtx, HOST_WIDE_INT); extern bool riscv_legitimize_move (machine_mode, rtx, rtx); extern rtx riscv_subword (rtx, bool); -extern bool riscv_split_64bit_move_p (rtx, rtx); +extern bool riscv_split_move_p (rtx, rtx); extern void riscv_split_doubleword_move (rtx, rtx); extern const char *riscv_output_move (rtx, rtx); extern const char *riscv_output_gpr_save (unsigned); diff --git a/gcc/config/riscv/riscv.c b/gcc/config/riscv/riscv.c index 57b2edbcb430..53f028460a62 100644 --- a/gcc/config/riscv/riscv.c +++ b/gcc/config/riscv/riscv.c @@ -217,6 +217,9 @@ struct riscv_cpu_info { /* Whether unaligned accesses execute very slowly. */ bool riscv_slow_unaligned_access; +/* Stack alignment to assume/maintain. */ +unsigned riscv_stack_boundary; + /* Which tuning parameters to use. */ static const struct riscv_tune_info *tune_info; @@ -864,7 +867,7 @@ riscv_load_store_insns (rtx mem, rtx_insn *insn) else if (GET_MODE_BITSIZE (mode) == 64) { set = single_set (insn); - if (set && !riscv_split_64bit_move_p (SET_DEST (set), SET_SRC (set))) + if (set && !riscv_split_move_p (SET_DEST (set), SET_SRC (set))) might_split_p = false; } @@ -1330,6 +1333,22 @@ riscv_legitimize_move (machine_mode mode, rtx dest, rtx src) return true; } + /* RISC-V GCC may generate non-legitimate address due to we provide some + pattern for optimize access PIC local symbol and it's make GCC generate + unrecognizable instruction during optmizing. */ + + if (MEM_P (dest) && !riscv_legitimate_address_p (mode, XEXP (dest, 0), + reload_completed)) + { + XEXP (dest, 0) = riscv_force_address (XEXP (dest, 0), mode); + } + + if (MEM_P (src) && !riscv_legitimate_address_p (mode, XEXP (src, 0), + reload_completed)) + { + XEXP (src, 0) = riscv_force_address (XEXP (src, 0), mode); + } + return false; } @@ -1632,12 +1651,14 @@ riscv_address_cost (rtx addr, machine_mode mode, rtx riscv_subword (rtx op, bool high_p) { - unsigned int byte = high_p ? UNITS_PER_WORD : 0; + unsigned int byte; machine_mode mode = GET_MODE (op); if (mode == VOIDmode) mode = TARGET_64BIT ? TImode : DImode; + byte = high_p ? (GET_MODE_SIZE (mode) / 2) : 0; + if (MEM_P (op)) return adjust_address (op, word_mode, byte); @@ -1647,17 +1668,20 @@ riscv_subword (rtx op, bool high_p) return simplify_gen_subreg (word_mode, op, mode, byte); } -/* Return true if a 64-bit move from SRC to DEST should be split into two. */ +/* Return true if move from SRC to DEST should be split into two. */ bool -riscv_split_64bit_move_p (rtx dest, rtx src) +riscv_split_move_p (rtx dest, rtx src) { - if (TARGET_64BIT) + enum machine_mode mode; + mode = GET_MODE (dest); + + if (GET_MODE_SIZE (mode) <= UNITS_PER_WORD) return false; /* Allow FPR <-> FPR and FPR <-> MEM moves, and permit the special case of zeroing an FPR with FCVT.D.W. */ - if (TARGET_DOUBLE_FLOAT + if ((GET_MODE_SIZE (mode) <= UNITS_PER_FP_REG) && ((FP_REG_RTX_P (src) && FP_REG_RTX_P (dest)) || (FP_REG_RTX_P (dest) && MEM_P (src)) || (FP_REG_RTX_P (src) && MEM_P (dest)) @@ -1668,7 +1692,7 @@ riscv_split_64bit_move_p (rtx dest, rtx src) } /* Split a doubleword move from SRC to DEST. On 32-bit targets, - this function handles 64-bit moves for which riscv_split_64bit_move_p + this function handles 64-bit moves for which riscv_split_move_p holds. For 64-bit targets, this function handles 128-bit moves. */ void @@ -1699,20 +1723,23 @@ riscv_output_move (rtx dest, rtx src) { enum rtx_code dest_code, src_code; machine_mode mode; - bool dbl_p; dest_code = GET_CODE (dest); src_code = GET_CODE (src); mode = GET_MODE (dest); - dbl_p = (GET_MODE_SIZE (mode) == 8); - if (dbl_p && riscv_split_64bit_move_p (dest, src)) + if (riscv_split_move_p (dest, src)) return "#"; if (dest_code == REG && GP_REG_P (REGNO (dest))) { if (src_code == REG && FP_REG_P (REGNO (src))) - return dbl_p ? "fmv.x.d\t%0,%1" : "fmv.x.s\t%0,%1"; + switch (GET_MODE_SIZE (mode)) + { + case 4: return "fmv.x.s\t%0,%1"; + case 8: return "fmv.x.d\t%0,%1"; + case 16: return "fmv.x.q\t%0,%1"; + } if (src_code == MEM) switch (GET_MODE_SIZE (mode)) @@ -1748,13 +1775,39 @@ riscv_output_move (rtx dest, rtx src) if (FP_REG_P (REGNO (dest))) { - if (!dbl_p) - return "fmv.s.x\t%0,%z1"; - if (TARGET_64BIT) - return "fmv.d.x\t%0,%z1"; - /* in RV32, we can emulate fmv.d.x %0, x0 using fcvt.d.w */ - gcc_assert (src == CONST0_RTX (mode)); - return "fcvt.d.w\t%0,x0"; + switch (GET_MODE_SIZE (mode)) + { + case 4: + return "fmv.s.x\t%0,%z1"; + case 8: + if (TARGET_64BIT) + return "fmv.d.x\t%0,%z1"; + else + { + /* In RV32, we can emulate fmv.d.x %0, x0 using + fcvt.d.w. */ + gcc_assert (src == CONST0_RTX (mode)); + return "fcvt.d.w\t%0,x0"; + } + case 16: + { + gcc_assert (src == CONST0_RTX (mode)); + if (TARGET_64BIT) + { + /* In RV64, we can emulate fmv.q.x %0, x0 using + fcvt.d.x. */ + return "fmv.d.x\t%0,x0"; + } + else + { + /* In RV32, we can emulate fmv.d.x %0, x0 using + fcvt.d.w. */ + gcc_assert (src == CONST0_RTX (mode)); + return "fcvt.d.w\t%0,x0"; + } + + } + } } } if (dest_code == MEM) @@ -1769,15 +1822,31 @@ riscv_output_move (rtx dest, rtx src) if (src_code == REG && FP_REG_P (REGNO (src))) { if (dest_code == REG && FP_REG_P (REGNO (dest))) - return dbl_p ? "fmv.d\t%0,%1" : "fmv.s\t%0,%1"; + switch (GET_MODE_SIZE (mode)) + { + case 4: return "fmv.s\t%0,%1"; + case 8: return "fmv.d\t%0,%1"; + case 16: return "fmv.q\t%0,%1"; + } if (dest_code == MEM) - return dbl_p ? "fsd\t%1,%0" : "fsw\t%1,%0"; + switch (GET_MODE_SIZE (mode)) + { + case 4: return "fsw\t%1,%0"; + case 8: return "fsd\t%1,%0"; + case 16: return "fsq\t%1,%0"; + } + } if (dest_code == REG && FP_REG_P (REGNO (dest))) { if (src_code == MEM) - return dbl_p ? "fld\t%0,%1" : "flw\t%0,%1"; + switch (GET_MODE_SIZE (mode)) + { + case 4: return "flw\t%0,%1"; + case 8: return "fld\t%0,%1"; + case 16: return "flq\t%0,%1"; + } } gcc_unreachable (); } @@ -2035,6 +2104,10 @@ riscv_emit_float_compare (enum rtx_code *code, rtx *op0, rtx *op1) emit_insn (gen_f##CMP##_quietdfdi4 (*op0, cmp_op0, cmp_op1)); \ else if (GET_MODE (cmp_op0) == DFmode) \ emit_insn (gen_f##CMP##_quietdfsi4 (*op0, cmp_op0, cmp_op1)); \ + else if (GET_MODE (cmp_op0) == TFmode && TARGET_64BIT) \ + emit_insn (gen_f##CMP##_quiettfdi4 (*op0, cmp_op0, cmp_op1)); \ + else if (GET_MODE (cmp_op0) == TFmode) \ + emit_insn (gen_f##CMP##_quiettfsi4 (*op0, cmp_op0, cmp_op1)); \ else \ gcc_unreachable (); \ *op1 = const0_rtx; \ @@ -2715,7 +2788,8 @@ riscv_memmodel_needs_release_fence (enum memmodel model) 'C' Print the integer branch condition for comparison OP. 'A' Print the atomic operation suffix for memory model OP. 'F' Print a FENCE if the memory model requires a release. - 'z' Print x0 if OP is zero, otherwise print OP normally. */ + 'z' Print x0 if OP is zero, otherwise print OP normally. + 'i' Print i if the operand is not a register. */ static void riscv_print_operand (FILE *file, rtx op, int letter) @@ -2750,6 +2824,11 @@ riscv_print_operand (FILE *file, rtx op, int letter) fputs ("fence iorw,ow; ", file); break; + case 'i': + if (code != REG) + fputs ("i", file); + break; + default: switch (code) { @@ -2833,6 +2912,22 @@ riscv_in_small_data_p (const_tree x) return riscv_size_ok_for_small_data_p (int_size_in_bytes (TREE_TYPE (x))); } +/* Switch to the appropriate section for output of DECL. */ + +static section * +riscv_select_section (tree decl, int reloc, + unsigned HOST_WIDE_INT align) +{ + switch (categorize_decl_for_section (decl, reloc)) + { + case SECCAT_SRODATA: + return get_named_section (decl, ".srodata", reloc); + + default: + return default_elf_select_section (decl, reloc, align); + } +} + /* Return a section for X, handling small data. */ static section * @@ -3014,7 +3109,15 @@ riscv_compute_frame_info (void) /* Only use save/restore routines if they don't alter the stack size. */ if (RISCV_STACK_ALIGN (num_save_restore * UNITS_PER_WORD) == x_save_size) - frame->save_libcall_adjustment = x_save_size; + { + if (TARGET_RVE && riscv_use_save_libcall (frame)) + { + /* Libcall saves/restores 3 registers at once, so we need + allocate 12 bytes for callee-saved register. */ + x_save_size = 3 * UNITS_PER_WORD; + } + frame->save_libcall_adjustment = x_save_size; + } offset += x_save_size; } @@ -3140,7 +3243,10 @@ riscv_for_each_saved_reg (HOST_WIDE_INT sp_offset, riscv_save_restore_fn fn) for (int regno = FP_REG_FIRST; regno <= FP_REG_LAST; regno++) if (BITSET_P (cfun->machine->frame.fmask, regno - FP_REG_FIRST)) { - machine_mode mode = TARGET_DOUBLE_FLOAT ? DFmode : SFmode; + machine_mode mode = + (TARGET_QUAD_FLOAT + ? TFmode + : (TARGET_DOUBLE_FLOAT ? DFmode : SFmode)); riscv_save_restore_reg (mode, regno, offset, fn); offset -= GET_MODE_SIZE (mode); @@ -3728,9 +3834,13 @@ riscv_option_override (void) /* Use -mtune's setting for slow_unaligned_access, even when optimizing for size. For architectures that trap and emulate unaligned accesses, - the performance cost is too great, even for -Os. */ + the performance cost is too great, even for -Os. Similarly, if + -m[no-]strict-align is left unspecified, heed -mtune's advice. */ riscv_slow_unaligned_access = (cpu->tune_info->slow_unaligned_access || TARGET_STRICT_ALIGN); + if ((target_flags_explicit & MASK_STRICT_ALIGN) == 0 + && cpu->tune_info->slow_unaligned_access) + target_flags |= MASK_STRICT_ALIGN; /* If the user hasn't specified a branch cost, use the processor's default. */ @@ -3757,6 +3867,20 @@ riscv_option_override (void) /* We do not yet support ILP32 on RV64. */ if (BITS_PER_WORD != POINTER_SIZE) error ("ABI requires -march=rv%d", POINTER_SIZE); + + /* Validate -mpreferred-stack-boundary= value. */ + riscv_stack_boundary = ABI_STACK_BOUNDARY; + if (riscv_preferred_stack_boundary_arg) + { + int min = ctz_hwi (MIN_STACK_BOUNDARY / 8); + int max = 8; + + if (!IN_RANGE (riscv_preferred_stack_boundary_arg, min, max)) + error ("-mpreferred-stack-boundary=%d must be between %d and %d", + riscv_preferred_stack_boundary_arg, min, max); + + riscv_stack_boundary = 8 << riscv_preferred_stack_boundary_arg; + } } /* Implement TARGET_CONDITIONAL_REGISTER_USAGE. */ @@ -3764,6 +3888,17 @@ riscv_option_override (void) static void riscv_conditional_register_usage (void) { + /* We have only x0~x15 on RV32E. */ + if (TARGET_RVE) + { + int r; + for (r = 16; r <= 31; r++) + { + fixed_regs[r] = 1; + call_used_regs[r] = call_really_used_regs[r] = 1; + } + } + if (!TARGET_HARD_FLOAT) { for (int regno = FP_REG_FIRST; regno <= FP_REG_LAST; regno++) @@ -4054,6 +4189,12 @@ riscv_cannot_copy_insn_p (rtx_insn *insn) #undef TARGET_IN_SMALL_DATA_P #define TARGET_IN_SMALL_DATA_P riscv_in_small_data_p +#undef TARGET_HAVE_SRODATA_SECTION +#define TARGET_HAVE_SRODATA_SECTION true + +#undef TARGET_ASM_SELECT_SECTION +#define TARGET_ASM_SELECT_SECTION riscv_select_section + #undef TARGET_ASM_SELECT_RTX_SECTION #define TARGET_ASM_SELECT_RTX_SECTION riscv_elf_select_rtx_section diff --git a/gcc/config/riscv/riscv.h b/gcc/config/riscv/riscv.h index c5d134cbe57e..e6248195cb56 100644 --- a/gcc/config/riscv/riscv.h +++ b/gcc/config/riscv/riscv.h @@ -99,12 +99,16 @@ along with GCC; see the file COPYING3. If not see #endif /* The `Q' extension is not yet supported. */ -#define UNITS_PER_FP_REG (TARGET_DOUBLE_FLOAT ? 8 : 4) +#define UNITS_PER_FP_REG (TARGET_QUAD_FLOAT ? 16 : (TARGET_DOUBLE_FLOAT ? 8 : 4)) /* The largest type that can be passed in floating-point registers. */ #define UNITS_PER_FP_ARG \ (riscv_abi == ABI_ILP32 || riscv_abi == ABI_LP64 ? 0 : \ - riscv_abi == ABI_ILP32F || riscv_abi == ABI_LP64F ? 4 : 8) \ + riscv_abi == ABI_ILP32F || riscv_abi == ABI_LP64F ? 4 : \ + riscv_abi == ABI_ILP32D || riscv_abi == ABI_LP64D ? 8 : 16) + +#define TARGET_HAVE_DOUBLE_FLOAT (TARGET_DOUBLE_FLOAT || TARGET_QUAD_FLOAT) +#define TARGET_HAVE_QUAD_FLOAT TARGET_QUAD_FLOAT /* Set the sizes of the core types. */ #define SHORT_TYPE_SIZE 16 @@ -123,8 +127,14 @@ along with GCC; see the file COPYING3. If not see /* Allocation boundary (in *bits*) for the code of a function. */ #define FUNCTION_BOUNDARY (TARGET_RVC ? 16 : 32) +/* The smallest supported stack boundary the calling convention supports. */ +#define MIN_STACK_BOUNDARY (TARGET_RVE ? BITS_PER_WORD : 2 * BITS_PER_WORD) + +/* The ABI stack alignment. */ +#define ABI_STACK_BOUNDARY (TARGET_RVE ? BITS_PER_WORD : 128) + /* There is no point aligning anything to a rounder boundary than this. */ -#define BIGGEST_ALIGNMENT 128 +#define BIGGEST_ALIGNMENT STACK_BOUNDARY /* The user-level ISA permits unaligned accesses, but they are not required of the privileged architecture. */ @@ -274,7 +284,7 @@ along with GCC; see the file COPYING3. If not see /* Internal macros to classify an ISA register's type. */ #define GP_REG_FIRST 0 -#define GP_REG_LAST 31 +#define GP_REG_LAST (TARGET_RVE ? 15 : 31) #define GP_REG_NUM (GP_REG_LAST - GP_REG_FIRST + 1) #define FP_REG_FIRST 32 @@ -513,7 +523,7 @@ enum reg_class `crtl->outgoing_args_size'. */ #define OUTGOING_REG_PARM_STACK_SPACE(FNTYPE) 1 -#define STACK_BOUNDARY 128 +#define STACK_BOUNDARY riscv_stack_boundary /* Symbolic macros for the registers used to return integer and floating point values. */ @@ -521,7 +531,7 @@ enum reg_class #define GP_RETURN GP_ARG_FIRST #define FP_RETURN (UNITS_PER_FP_ARG == 0 ? GP_RETURN : FP_ARG_FIRST) -#define MAX_ARGS_IN_REGISTERS 8 +#define MAX_ARGS_IN_REGISTERS (TARGET_RVE ? 6 : 8) /* Symbolic macros for the first/last argument registers. */ @@ -569,8 +579,10 @@ typedef struct { #define EPILOGUE_USES(REGNO) ((REGNO) == RETURN_ADDR_REGNUM) -/* ABI requires 16-byte alignment, even on RV32. */ -#define RISCV_STACK_ALIGN(LOC) (((LOC) + 15) & -16) +/* ABI requires 16-byte alignment, even on RV32, + but 4-byte alignment for RVE. */ +#define RISCV_STACK_ALIGN(LOC) \ + (((LOC) + (BIGGEST_ALIGNMENT / 8) - 1) & -(BIGGEST_ALIGNMENT / 8)) /* EXIT_IGNORE_STACK should be nonzero if, when returning from a function, the stack pointer does not matter. The value is tested only in @@ -656,7 +668,7 @@ typedef struct { #define MOVE_MAX UNITS_PER_WORD #define MAX_MOVE_MAX 8 -#define SLOW_BYTE_ACCESS 0 +#define SLOW_BYTE_ACCESS 1 #define SHIFT_COUNT_TRUNCATED 1 @@ -866,6 +878,7 @@ while (0) extern const enum reg_class riscv_regno_to_class[]; extern bool riscv_hard_regno_mode_ok[][FIRST_PSEUDO_REGISTER]; extern bool riscv_slow_unaligned_access; +extern unsigned riscv_stack_boundary; #endif #define ASM_PREFERRED_EH_DATA_FORMAT(CODE,GLOBAL) \ diff --git a/gcc/config/riscv/riscv.md b/gcc/config/riscv/riscv.md index 18dba3beea1d..dad7c5853ad7 100644 --- a/gcc/config/riscv/riscv.md +++ b/gcc/config/riscv/riscv.md @@ -259,6 +259,9 @@ ;; Iterator for QImode extension patterns. (define_mode_iterator SUPERQI [HI SI (DI "TARGET_64BIT")]) +;; Iterator for extending loads. +(define_mode_iterator ZERO_EXTEND_LOAD [QI HI (SI "TARGET_64BIT")]) + ;; Iterator for hardware integer modes narrower than XLEN. (define_mode_iterator SUBX [QI HI (SI "TARGET_64BIT")]) @@ -267,24 +270,25 @@ ;; Iterator for hardware-supported floating-point modes. (define_mode_iterator ANYF [(SF "TARGET_HARD_FLOAT") - (DF "TARGET_DOUBLE_FLOAT")]) + (DF "TARGET_HAVE_DOUBLE_FLOAT") + (TF "TARGET_HAVE_QUAD_FLOAT")]) ;; This attribute gives the length suffix for a sign- or zero-extension ;; instruction. (define_mode_attr size [(QI "b") (HI "h")]) ;; Mode attributes for loads. -(define_mode_attr load [(QI "lb") (HI "lh") (SI "lw") (DI "ld") (SF "flw") (DF "fld")]) +(define_mode_attr load [(QI "lb") (HI "lh") (SI "lw") (DI "ld") (SF "flw") (DF "fld") (TF "flq")]) ;; Instruction names for stores. -(define_mode_attr store [(QI "sb") (HI "sh") (SI "sw") (DI "sd") (SF "fsw") (DF "fsd")]) +(define_mode_attr store [(QI "sb") (HI "sh") (SI "sw") (DI "sd") (SF "fsw") (DF "fsd") (TF "fsq")]) ;; This attribute gives the best constraint to use for registers of ;; a given mode. (define_mode_attr reg [(SI "d") (DI "d") (CC "d")]) ;; This attribute gives the format suffix for floating-point operations. -(define_mode_attr fmt [(SF "s") (DF "d")]) +(define_mode_attr fmt [(SF "s") (DF "d") (TF "q")]) ;; This attribute gives the integer suffix for floating-point conversions. (define_mode_attr ifmt [(SI "w") (DI "l")]) @@ -294,7 +298,7 @@ ;; This attribute gives the upper-case mode name for one unit of a ;; floating-point mode. -(define_mode_attr UNITMODE [(SF "SF") (DF "DF")]) +(define_mode_attr UNITMODE [(SF "SF") (DF "DF") (TF "TF")]) ;; This attribute gives the integer mode that has half the size of ;; the controlling mode. @@ -411,7 +415,7 @@ (plus:SI (match_operand:SI 1 "register_operand" " r,r") (match_operand:SI 2 "arith_operand" " r,I")))] "" - { return TARGET_64BIT ? "addw\t%0,%1,%2" : "add\t%0,%1,%2"; } + { return TARGET_64BIT ? "add%i2w\t%0,%1,%2" : "add%i2\t%0,%1,%2"; } [(set_attr "type" "arith") (set_attr "mode" "SI")]) @@ -420,7 +424,7 @@ (plus:DI (match_operand:DI 1 "register_operand" " r,r") (match_operand:DI 2 "arith_operand" " r,I")))] "TARGET_64BIT" - "add\t%0,%1,%2" + "add%i2\t%0,%1,%2" [(set_attr "type" "arith") (set_attr "mode" "DI")]) @@ -430,7 +434,7 @@ (plus:SI (match_operand:SI 1 "register_operand" " r,r") (match_operand:SI 2 "arith_operand" " r,I"))))] "TARGET_64BIT" - "addw\t%0,%1,%2" + "add%i2w\t%0,%1,%2" [(set_attr "type" "arith") (set_attr "mode" "SI")]) @@ -441,7 +445,7 @@ (match_operand:DI 2 "arith_operand" " r,I")) 0)))] "TARGET_64BIT" - "addw\t%0,%1,%2" + "add%i2w\t%0,%1,%2" [(set_attr "type" "arith") (set_attr "mode" "SI")]) @@ -702,7 +706,7 @@ (any_div:SI (match_operand:SI 1 "register_operand" " r") (match_operand:SI 2 "register_operand" " r")))] "TARGET_DIV" - { return TARGET_64BIT ? "w\t%0,%1,%2" : "\t%0,%1,%2"; } + { return TARGET_64BIT ? "%i2w\t%0,%1,%2" : "%i2\t%0,%1,%2"; } [(set_attr "type" "idiv") (set_attr "mode" "SI")]) @@ -711,7 +715,7 @@ (any_div:DI (match_operand:DI 1 "register_operand" " r") (match_operand:DI 2 "register_operand" " r")))] "TARGET_DIV && TARGET_64BIT" - "\t%0,%1,%2" + "%i2\t%0,%1,%2" [(set_attr "type" "idiv") (set_attr "mode" "DI")]) @@ -721,7 +725,7 @@ (any_div:SI (match_operand:SI 1 "register_operand" " r") (match_operand:SI 2 "register_operand" " r"))))] "TARGET_DIV && TARGET_64BIT" - "w\t%0,%1,%2" + "%i2w\t%0,%1,%2" [(set_attr "type" "idiv") (set_attr "mode" "DI")]) @@ -925,7 +929,7 @@ (any_bitwise:X (match_operand:X 1 "register_operand" "%r,r") (match_operand:X 2 "arith_operand" " r,I")))] "" - "\t%0,%1,%2" + "%i2\t%0,%1,%2" [(set_attr "type" "logical") (set_attr "mode" "")]) @@ -934,7 +938,7 @@ (any_bitwise:SI (match_operand:SI 1 "register_operand" "%r,r") (match_operand:SI 2 "arith_operand" " r,I")))] "TARGET_64BIT" - "\t%0,%1,%2" + "%i2\t%0,%1,%2" [(set_attr "type" "logical") (set_attr "mode" "SI")]) @@ -965,11 +969,27 @@ [(set (match_operand:SF 0 "register_operand" "=f") (float_truncate:SF (match_operand:DF 1 "register_operand" " f")))] - "TARGET_DOUBLE_FLOAT" + "TARGET_HAVE_DOUBLE_FLOAT" "fcvt.s.d\t%0,%1" [(set_attr "type" "fcvt") (set_attr "mode" "SF")]) +(define_insn "trunctfsf2" + [(set (match_operand:SF 0 "register_operand" "=f") + (float_truncate:SF (match_operand:TF 1 "register_operand" "f")))] + "TARGET_HAVE_QUAD_FLOAT" + "fcvt.s.q\t%0,%1" + [(set_attr "type" "fcvt") + (set_attr "mode" "SF")]) + +(define_insn "trunctfdf2" + [(set (match_operand:DF 0 "register_operand" "=f") + (float_truncate:DF (match_operand:TF 1 "register_operand" "f")))] + "TARGET_HAVE_QUAD_FLOAT" + "fcvt.d.q\t%0,%1" + [(set_attr "type" "fcvt") + (set_attr "mode" "DF")]) + ;; ;; .................... ;; @@ -1022,7 +1042,7 @@ (match_operand:QI 1 "nonimmediate_operand" " r,m")))] "" "@ - and\t%0,%1,0xff + andi\t%0,%1,0xff lbu\t%0,%1" [(set_attr "move_type" "andi,load") (set_attr "mode" "")]) @@ -1069,11 +1089,27 @@ [(set (match_operand:DF 0 "register_operand" "=f") (float_extend:DF (match_operand:SF 1 "register_operand" " f")))] - "TARGET_DOUBLE_FLOAT" + "TARGET_HAVE_DOUBLE_FLOAT" "fcvt.d.s\t%0,%1" [(set_attr "type" "fcvt") (set_attr "mode" "DF")]) +(define_insn "extendsftf2" + [(set (match_operand:TF 0 "register_operand" "=f") + (float_extend:TF (match_operand:SF 1 "register_operand" "f")))] + "TARGET_HAVE_QUAD_FLOAT" + "fcvt.q.s\t%0,%1" + [(set_attr "type" "fcvt") + (set_attr "mode" "TF")]) + +(define_insn "extenddftf2" + [(set (match_operand:TF 0 "register_operand" "=f") + (float_extend:TF (match_operand:DF 1 "register_operand" "f")))] + "TARGET_HAVE_QUAD_FLOAT" + "fcvt.q.d\t%0,%1" + [(set_attr "type" "fcvt") + (set_attr "mode" "TF")]) + ;; ;; .................... ;; @@ -1314,7 +1350,7 @@ (plus:HI (match_operand:HISI 1 "register_operand" " r,r") (match_operand:HISI 2 "arith_operand" " r,I")))] "" - { return TARGET_64BIT ? "addw\t%0,%1,%2" : "add\t%0,%1,%2"; } + { return TARGET_64BIT ? "add%i2w\t%0,%1,%2" : "add%i2\t%0,%1,%2"; } [(set_attr "type" "arith") (set_attr "mode" "HI")]) @@ -1323,7 +1359,7 @@ (xor:HI (match_operand:HISI 1 "register_operand" " r,r") (match_operand:HISI 2 "arith_operand" " r,I")))] "" - "xor\t%0,%1,%2" + "xor%i2\t%0,%1,%2" [(set_attr "type" "logical") (set_attr "mode" "HI")]) @@ -1394,7 +1430,7 @@ (define_insn "*movdf_hardfloat_rv32" [(set (match_operand:DF 0 "nonimmediate_operand" "=f,f,f,m,m, *r,*r,*m") (match_operand:DF 1 "move_operand" " f,G,m,f,G,*r*G,*m,*r"))] - "!TARGET_64BIT && TARGET_DOUBLE_FLOAT + "!TARGET_64BIT && TARGET_HAVE_DOUBLE_FLOAT && (register_operand (operands[0], DFmode) || reg_or_0_operand (operands[1], DFmode))" { return riscv_output_move (operands[0], operands[1]); } @@ -1404,7 +1440,7 @@ (define_insn "*movdf_hardfloat_rv64" [(set (match_operand:DF 0 "nonimmediate_operand" "=f,f,f,m,m,*f,*r, *r,*r,*m") (match_operand:DF 1 "move_operand" " f,G,m,f,G,*r,*f,*r*G,*m,*r"))] - "TARGET_64BIT && TARGET_DOUBLE_FLOAT + "TARGET_64BIT && TARGET_HAVE_DOUBLE_FLOAT && (register_operand (operands[0], DFmode) || reg_or_0_operand (operands[1], DFmode))" { return riscv_output_move (operands[0], operands[1]); } @@ -1414,7 +1450,7 @@ (define_insn "*movdf_softfloat" [(set (match_operand:DF 0 "nonimmediate_operand" "= r,r, m") (match_operand:DF 1 "move_operand" " rG,m,rG"))] - "!TARGET_DOUBLE_FLOAT + "!TARGET_HAVE_DOUBLE_FLOAT && (register_operand (operands[0], DFmode) || reg_or_0_operand (operands[1], DFmode))" { return riscv_output_move (operands[0], operands[1]); } @@ -1425,7 +1461,40 @@ [(set (match_operand:MOVE64 0 "nonimmediate_operand") (match_operand:MOVE64 1 "move_operand"))] "reload_completed - && riscv_split_64bit_move_p (operands[0], operands[1])" + && riscv_split_move_p (operands[0], operands[1])" + [(const_int 0)] +{ + riscv_split_doubleword_move (operands[0], operands[1]); + DONE; +}) + +;; 128-bit floating point moves +(define_expand "movtf" + [(set (match_operand:TF 0 "") + (match_operand:TF 1 ""))] + "TARGET_HAVE_QUAD_FLOAT" +{ + if (riscv_legitimize_move (TFmode, operands[0], operands[1])) + DONE; +}) + +;; In RV64, we lack fmv.x.q and fmv.q.x. Go through memory instead. +;; (However, we can still use fcvt.q.w to zero a floating-point register.) +(define_insn "*movtf_hardfloat_rv64" + [(set (match_operand:TF 0 "nonimmediate_operand" "=f,f,f,m,m, *r,*r,*m") + (match_operand:TF 1 "move_operand" " f,G,m,f,G,*r*G,*m,*r"))] + "TARGET_64BIT && TARGET_HAVE_QUAD_FLOAT + && (register_operand (operands[0], TFmode) + || reg_or_0_operand (operands[1], TFmode))" + { return riscv_output_move (operands[0], operands[1]); } + [(set_attr "move_type" "fmove,mtc,fpload,fpstore,store,move,load,store") + (set_attr "mode" "TF")]) + +(define_split + [(set (match_operand:TF 0 "nonimmediate_operand") + (match_operand:TF 1 "move_operand"))] + "reload_completed + && riscv_split_move_p (operands[0], operands[1])" [(const_int 0)] { riscv_split_doubleword_move (operands[0], operands[1]); @@ -1471,7 +1540,7 @@ operands[2] = GEN_INT (INTVAL (operands[2]) & (GET_MODE_BITSIZE (SImode) - 1)); - return TARGET_64BIT ? "w\t%0,%1,%2" : "\t%0,%1,%2"; + return TARGET_64BIT ? "%i2w\t%0,%1,%2" : "%i2\t%0,%1,%2"; } [(set_attr "type" "shift") (set_attr "mode" "SI")]) @@ -1487,7 +1556,7 @@ operands[2] = GEN_INT (INTVAL (operands[2]) & (GET_MODE_BITSIZE (DImode) - 1)); - return "\t%0,%1,%2"; + return "%i2\t%0,%1,%2"; } [(set_attr "type" "shift") (set_attr "mode" "DI")]) @@ -1502,7 +1571,21 @@ if (GET_CODE (operands[2]) == CONST_INT) operands[2] = GEN_INT (INTVAL (operands[2]) & 0x1f); - return "w\t%0,%1,%2"; + return "%i2w\t%0,%1,%2"; +} + [(set_attr "type" "shift") + (set_attr "mode" "SI")]) + +(define_insn "*lshrsi3_zero_extend" + [(set (match_operand:DI 0 "register_operand" "=r") + (zero_extend:DI + (lshiftrt:SI (match_operand:SI 1 "register_operand" " r") + (match_operand:SI 2 "const_int_operand"))))] + "TARGET_64BIT && (INTVAL (operands[2]) & 0x1f) > 0" +{ + operands[2] = GEN_INT (INTVAL (operands[2]) & 0x1f); + + return "srlw\t%0,%1,%2"; } [(set_attr "type" "shift") (set_attr "mode" "SI")]) @@ -1721,7 +1804,7 @@ (any_ge:GPR (match_operand:X 1 "register_operand" " r") (const_int 1)))] "" - "slt\t%0,zero,%1" + "slt%i2\t%0,zero,%1" [(set_attr "type" "slt") (set_attr "mode" "")]) @@ -1730,7 +1813,7 @@ (any_lt:GPR (match_operand:X 1 "register_operand" " r") (match_operand:X 2 "arith_operand" " rI")))] "" - "slt\t%0,%1,%2" + "slt%i2\t%0,%1,%2" [(set_attr "type" "slt") (set_attr "mode" "")]) @@ -1741,7 +1824,7 @@ "" { operands[2] = GEN_INT (INTVAL (operands[2]) + 1); - return "slt\t%0,%1,%2"; + return "slt%i2\t%0,%1,%2"; } [(set_attr "type" "slt") (set_attr "mode" "")]) diff --git a/gcc/config/riscv/riscv.opt b/gcc/config/riscv/riscv.opt index cfd0335d082c..e3b3a7e7c903 100644 --- a/gcc/config/riscv/riscv.opt +++ b/gcc/config/riscv/riscv.opt @@ -33,6 +33,10 @@ mabi= Target Report RejectNegative Joined Enum(abi_type) Var(riscv_abi) Init(ABI_ILP32) Specify integer and floating-point calling convention. +mpreferred-stack-boundary= +Target RejectNegative Joined UInteger Var(riscv_preferred_stack_boundary_arg) +Attempt to keep stack aligned to this power of 2. + Enum Name(abi_type) Type(enum riscv_abi_type) Supported ABIs (for use with the -mabi= option): @@ -55,6 +59,9 @@ Enum(abi_type) String(lp64f) Value(ABI_LP64F) EnumValue Enum(abi_type) String(lp64d) Value(ABI_LP64D) +EnumValue +Enum(abi_type) String(lp64q) Value(ABI_LP64Q) + mfdiv Target Report Mask(FDIV) Use hardware floating-point divide and square root instructions. @@ -112,4 +119,8 @@ Mask(HARD_FLOAT) Mask(DOUBLE_FLOAT) +Mask(QUAD_FLOAT) + Mask(RVC) + +Mask(RVE) diff --git a/gcc/doc/invoke.texi b/gcc/doc/invoke.texi index 5ae9dc4128d5..49b38140a87f 100644 --- a/gcc/doc/invoke.texi +++ b/gcc/doc/invoke.texi @@ -985,7 +985,7 @@ See RS/6000 and PowerPC Options. -msmall-data-limit=@var{N-bytes} @gol -msave-restore -mno-save-restore @gol -mstrict-align -mno-strict-align @gol --mcmodel=@var{code-model} @gol +-mcmodel=medlow -mcmodel=medany @gol -mexplicit-relocs -mno-explicit-relocs @gol} @emph{RL78 Options} @@ -21488,9 +21488,18 @@ Use smaller but slower prologue and epilogue code. @opindex mstrict-align Do not generate unaligned memory accesses. -@item -mcmodel=@var{code-model} -@opindex mcmodel -Specify the code model. +@item -mcmodel=medlow +@opindex mcmodel=medlow +Generate code for the medium-low code model. The program and its statically +defined symbols must lie within a single 2 GiB address range and must lie +between absolute addresses -2 GiB and +2 GiB. Programs can be statically or +dynamically linked. This is the default code model. + +@item -mcmodel=medany +@opindex mcmodel=medany +Generate code for the medium-any code model. The program and its statically +defined symbols must be within any single 2 GiB address range. Programs can be +statically or dynamically linked. @end table diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog index be58e3c877b0..4b318f95f1cf 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -1,3 +1,7 @@ +2017-08-03 Kito Cheng + + * testsuite/gcc.dg/stack-usage-1.c: Support for rv32e. + 2017-07-31 Steve Ellcey PR tree-optimization/80925 @@ -4107,8 +4111,8 @@ 2017-05-08 Wilco Dijkstra - * gcc.dg/vect/vect-44.c: Add -fno-vect-cost-model. - * gcc.dg/vect/vect-50.c: Likewise. + * testsuite/gcc.dg/vect/vect-44.c: Add -fno-vect-cost-model. + * gcc/testsuite/gcc.dg/vect/vect-50.c: Likewise. 2017-05-07 Jeff Law @@ -4842,7 +4846,7 @@ * gcc.dg/tree-ssa/vrp35.c: Disable EVRP. * gcc.dg/tree-ssa/vrp36.c: Likewise. * gcc.dg/tree-ssa/pr49039.c: Likewise. - + 2017-04-27 Marek Polacek PR sanitizer/80349 diff --git a/gcc/testsuite/gcc.dg/stack-usage-1.c b/gcc/testsuite/gcc.dg/stack-usage-1.c index 45d2c7b6aae0..038bd4ec05cc 100644 --- a/gcc/testsuite/gcc.dg/stack-usage-1.c +++ b/gcc/testsuite/gcc.dg/stack-usage-1.c @@ -64,7 +64,11 @@ # define SIZE 240 # endif #elif defined (__riscv) -# define SIZE 240 +# if defined (__riscv_32e) +# define SIZE 252 +# else +# define SIZE 240 +# endif #elif defined (__AVR__) #if defined (__AVR_3_BYTE_PC__ ) # define SIZE 251 /* 256 - 2 bytes for Y - 3 bytes for return address */ diff --git a/include/ChangeLog b/include/ChangeLog index bbcc87d418b7..8714b44a41c0 100644 --- a/include/ChangeLog +++ b/include/ChangeLog @@ -1,3 +1,9 @@ +2017-08-02 Kito Cheng + + * longlong.h [__riscv] (__umulsidi3): Define. + [__riscv] (umul_ppmm) Likewise. + [__riscv] (__muluw3) Likewise. + 2017-07-02 Jan Kratochvil * dwarf2.def (DW_IDX_compile_unit, DW_IDX_type_unit, DW_IDX_die_offset) diff --git a/include/longlong.h b/include/longlong.h index c24568acea07..e61947d6c307 100644 --- a/include/longlong.h +++ b/include/longlong.h @@ -1050,6 +1050,56 @@ extern UDItype __umulsidi3 (USItype, USItype); } while (0) #endif +#if defined(__riscv) +#ifdef __riscv_mul +#define __umulsidi3(u,v) ((UDWtype)(UWtype)(u) * (UWtype)(v)) +#define __muluw3(a, b) ((UWtype)(a) * (UWtype)(b)) +#else +#if __riscv_xlen == 32 + #define MULUW3 "call __mulsi3" +#elif __riscv_xlen == 64 + #define MULUW3 "call __muldi3" +#else +#error unsupport xlen +#endif /* __riscv_xlen */ +/* We rely on the fact that MULUW3 doesn't clobber the t-registers. */ +#define __muluw3(a, b) \ + ({ \ + register UWtype __op0 asm ("a0") = a; \ + register UWtype __op1 asm ("a1") = b; \ + asm volatile (MULUW3 \ + : "+r" (__op0), "+r" (__op1) \ + : \ + : "ra", "a2", "a3"); \ + __op0; \ + }) +#endif /* __riscv_mul */ +#define umul_ppmm(w1, w0, u, v) \ + do { \ + UWtype __x0, __x1, __x2, __x3; \ + UHWtype __ul, __vl, __uh, __vh; \ + \ + __ul = __ll_lowpart (u); \ + __uh = __ll_highpart (u); \ + __vl = __ll_lowpart (v); \ + __vh = __ll_highpart (v); \ + \ + __x0 = __muluw3 (__ul, __vl); \ + __x1 = __muluw3 (__ul, __vh); \ + __x2 = __muluw3 (__uh, __vl); \ + __x3 = __muluw3 (__uh, __vh); \ + \ + __x1 += __ll_highpart (__x0);/* this can't give carry */ \ + __x1 += __x2; /* but this indeed can */ \ + if (__x1 < __x2) /* did we get it? */ \ + __x3 += __ll_B; /* yes, add it in the proper pos. */ \ + \ + (w1) = __x3 + __ll_highpart (__x1); \ + (w0) = __muluw3 (__ll_lowpart (__x1), __ll_B) \ + + __ll_lowpart (__x0); \ + } while (0) +#endif /* __riscv */ + #if defined(__sh__) && W_TYPE_SIZE == 32 #ifndef __sh1__ #define umul_ppmm(w1, w0, u, v) \ diff --git a/libgcc/ChangeLog b/libgcc/ChangeLog index fc7b878d95c0..f8f19ad374ad 100644 --- a/libgcc/ChangeLog +++ b/libgcc/ChangeLog @@ -1,3 +1,15 @@ +2017-08-03 Kito Cheng + Monk Chiang + + * config.host: Support rv32e. + * config/riscv/save-restore.S: Support rv32e. + +2017-08-03 Kito Cheng + + * config/riscv/t-elf: Use multi3.c instead of multi3.S. + * config/riscv/multi3.c: New file. + * config/riscv/multi3.S: Remove. + 2017-07-28 Sebastian Huber * config/rs6000/ibm-ldouble.c: Disable if defined __rtems__. diff --git a/libgcc/config/riscv/multi3.S b/libgcc/config/riscv/multi3.S deleted file mode 100644 index 4d454e65013d..000000000000 --- a/libgcc/config/riscv/multi3.S +++ /dev/null @@ -1,81 +0,0 @@ -/* Integer multiplication routines for RISC-V. - - Copyright (C) 2016-2017 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. - -Under Section 7 of GPL version 3, you are granted additional -permissions described in the GCC Runtime Library Exception, version -3.1, as published by the Free Software Foundation. - -You should have received a copy of the GNU General Public License and -a copy of the GCC Runtime Library Exception along with this program; -see the files COPYING3 and COPYING.RUNTIME respectively. If not, see -. */ - - .text - .align 2 - -#if __riscv_xlen == 32 -/* Our RV64 64-bit routines are equivalent to our RV32 32-bit routines. */ -# define __multi3 __muldi3 -#endif - - .globl __multi3 -__multi3: - -#if __riscv_xlen == 32 -/* Our RV64 64-bit routines are equivalent to our RV32 32-bit routines. */ -# define __muldi3 __mulsi3 -#endif - -/* We rely on the fact that __muldi3 doesn't clobber the t-registers. */ - - mv t0, ra - mv t5, a0 - mv a0, a1 - mv t6, a3 - mv a1, t5 - mv a4, a2 - li a5, 0 - li t2, 0 - li t4, 0 -.L1: - add a6, t2, a1 - andi t3, a4, 1 - slli a7, a5, 1 - slti t1, a1, 0 - srli a4, a4, 1 - add a5, t4, a5 - beqz t3, .L2 - sltu t3, a6, t2 - mv t2, a6 - add t4, t3, a5 -.L2: - slli a1, a1, 1 - or a5, t1, a7 - bnez a4, .L1 - beqz a0, .L3 - mv a1, a2 - call __muldi3 - add t4, t4, a0 -.L3: - beqz t6, .L4 - mv a1, t6 - mv a0, t5 - call __muldi3 - add t4, t4, a0 -.L4: - mv a0, t2 - mv a1, t4 - jr t0 diff --git a/libgcc/config/riscv/multi3.c b/libgcc/config/riscv/multi3.c new file mode 100644 index 000000000000..b395ba8c4a22 --- /dev/null +++ b/libgcc/config/riscv/multi3.c @@ -0,0 +1,25 @@ +#include "tconfig.h" +#include "tsystem.h" +#include "coretypes.h" +#include "tm.h" +#include "libgcc_tm.h" +#define LIBGCC2_UNITS_PER_WORD (__riscv_xlen / 8) + +#include "libgcc2.h" + +#if __riscv_xlen == 32 + #define __multi3 __muldi3 +#endif + +DWtype +__multi3 (DWtype u, DWtype v) +{ + const DWunion uu = {.ll = u}; + const DWunion vv = {.ll = v}; + DWunion w = {.ll = __umulsidi3 (uu.s.low, vv.s.low)}; + + w.s.high += (__muluw3((UWtype) uu.s.low, (UWtype) vv.s.high) + + __muluw3((UWtype) uu.s.high, (UWtype) vv.s.low)); + + return w.ll; +} diff --git a/libgcc/config/riscv/save-restore.S b/libgcc/config/riscv/save-restore.S index 2073a73089bb..890043e44c5b 100644 --- a/libgcc/config/riscv/save-restore.S +++ b/libgcc/config/riscv/save-restore.S @@ -294,6 +294,40 @@ __riscv_restore_0: #else +#ifdef __riscv_32e +__riscv_save_2: +__riscv_save_1: +__riscv_save_0: + .cfi_startproc + # __riscv_save_* routine use t0/x5 as return address + .cfi_return_column 5 + addi sp, sp, -12 + .cfi_def_cfa_offset 12 + sw s1, 0(sp) + .cfi_offset 9, -12 + sw s0, 4(sp) + .cfi_offset 8, -8 + sw ra, 8(sp) + .cfi_offset 1, 0 + jr t0 + .cfi_endproc + +__riscv_restore_2: +__riscv_restore_1: +__riscv_restore_0: + .cfi_startproc + .cfi_def_cfa_offset 14 + lw s1, 0(sp) + .cfi_restore 9 + lw s0, 4(sp) + .cfi_restore 8 + lw ra, 8(sp) + .cfi_restore 1 + addi sp, sp, 12 + .cfi_def_cfa_offset 0 + ret + .cfi_endproc +#else __riscv_save_12: .cfi_startproc # __riscv_save_* routine use t0/x5 as return address @@ -459,5 +493,6 @@ __riscv_restore_0: .cfi_def_cfa_offset 0 ret .cfi_endproc +#endif /* __riscv_32e */ -#endif +#endif /* __riscv_xlen == 64 */ diff --git a/libgcc/config/riscv/t-elf b/libgcc/config/riscv/t-elf index 01d5ebaa417e..dbc8f85dfc5c 100644 --- a/libgcc/config/riscv/t-elf +++ b/libgcc/config/riscv/t-elf @@ -1,6 +1,6 @@ LIB2ADD += $(srcdir)/config/riscv/save-restore.S \ $(srcdir)/config/riscv/muldi3.S \ - $(srcdir)/config/riscv/multi3.S \ + $(srcdir)/config/riscv/multi3.c \ $(srcdir)/config/riscv/div.S \ $(srcdir)/config/riscv/atomic.c \