diff options
author | Jiuyang liu | 2019-06-25 08:38:31 +0000 |
---|---|---|
committer | Jiuyang liu | 2019-06-25 08:38:31 +0000 |
commit | ea4c1a3e9a89cd74a1e844f1db9d7b2ee78e9213 (patch) | |
tree | 34fc748ac62993dcdbf4c9daee922995b49b7d39 | |
download | aur-ea4c1a3e9a89cd74a1e844f1db9d7b2ee78e9213.tar.gz |
init
-rw-r--r-- | .SRCINFO | 28 | ||||
-rw-r--r-- | 0001-SiFive-CLIC-patches-for-preemptible-and-stack-swappi.patch | 644 | ||||
-rw-r--r-- | 0002-Finish-CLIC-support-resolving-patch-merge-error-and-.patch | 360 | ||||
-rw-r--r-- | 0003-RISC-V-Add-short-forward-branch-optimization-for-sif.patch | 284 | ||||
-rw-r--r-- | 0004-Remove-libgloss.patch | 17 | ||||
-rw-r--r-- | PKGBUILD | 97 |
6 files changed, 1430 insertions, 0 deletions
diff --git a/.SRCINFO b/.SRCINFO new file mode 100644 index 000000000000..3c51de06d195 --- /dev/null +++ b/.SRCINFO @@ -0,0 +1,28 @@ +pkgbase = riscv-sifive-elf-gcc-stage1 + pkgdesc = Cross compiler for 32-bit and 64-bit RISC-V + pkgver = 9.1.0 + pkgrel = 1 + url = https://gcc.gnu.org/ + arch = x86_64 + groups = risc-v + license = GPL + license = LGPL + license = FDL + makedepends = python + depends = riscv-sifive-elf-binutils + depends = libmpc + options = !emptydirs + options = !strip + source = https://gcc.gnu.org/pub/gcc/releases/gcc-9.1.0/gcc-9.1.0.tar.xz + source = 0001-SiFive-CLIC-patches-for-preemptible-and-stack-swappi.patch + source = 0002-Finish-CLIC-support-resolving-patch-merge-error-and-.patch + source = 0003-RISC-V-Add-short-forward-branch-optimization-for-sif.patch + source = 0004-Remove-libgloss.patch + md5sums = 6069ae3737cf02bf2cb44a391ef0e937 + md5sums = SKIP + md5sums = SKIP + md5sums = SKIP + md5sums = SKIP + +pkgname = riscv-sifive-elf-gcc-stage1 + diff --git a/0001-SiFive-CLIC-patches-for-preemptible-and-stack-swappi.patch b/0001-SiFive-CLIC-patches-for-preemptible-and-stack-swappi.patch new file mode 100644 index 000000000000..9be1181eba25 --- /dev/null +++ b/0001-SiFive-CLIC-patches-for-preemptible-and-stack-swappi.patch @@ -0,0 +1,644 @@ +From d79fde036c461b5fc410e1ef4fb3bac8a66088ca Mon Sep 17 00:00:00 2001 +From: Jim Wilson <jimw@sifive.com> +Date: Thu, 21 Feb 2019 19:50:46 -0800 +Subject: [PATCH 1/3] SiFive CLIC patches, for preemptible and stack-swapping + interrupt support. + +--- + gcc/config/riscv/constraints.md | 5 + + gcc/config/riscv/predicates.md | 4 + + gcc/config/riscv/riscv.c | 193 ++++++++++++++++-- + gcc/config/riscv/riscv.md | 57 ++++++ + gcc/doc/extend.texi | 25 +++ + gcc/doc/md.texi | 3 + + gcc/testsuite/gcc.target/riscv/interrupt-5.c | 15 ++ + .../gcc.target/riscv/preemptible-1.c | 11 + + .../gcc.target/riscv/preemptible-2.c | 11 + + .../gcc.target/riscv/preemptible-3.c | 9 + + gcc/testsuite/gcc.target/riscv/stack-swap-1.c | 18 ++ + 11 files changed, 330 insertions(+), 21 deletions(-) + create mode 100644 gcc/testsuite/gcc.target/riscv/preemptible-1.c + create mode 100644 gcc/testsuite/gcc.target/riscv/preemptible-2.c + create mode 100644 gcc/testsuite/gcc.target/riscv/preemptible-3.c + create mode 100644 gcc/testsuite/gcc.target/riscv/stack-swap-1.c + +diff --git a/gcc/config/riscv/constraints.md b/gcc/config/riscv/constraints.md +index b4de83f8324..a736013d9f6 100644 +--- a/gcc/config/riscv/constraints.md ++++ b/gcc/config/riscv/constraints.md +@@ -49,6 +49,11 @@ + (and (match_code "const_int") + (match_test "IN_RANGE (ival, 0, 31)"))) + ++(define_constraint "C" ++ "A 12-bit unsigned immediate for CSR address." ++ (and (match_code "const_int") ++ (match_test "IN_RANGE (ival, 0, IMM_REACH-1)"))) ++ + ;; Floating-point constant +0.0, used for FCVT-based moves when FMV is + ;; not available in RV32. + (define_constraint "G" +diff --git a/gcc/config/riscv/predicates.md b/gcc/config/riscv/predicates.md +index 83fc4bd663d..83e698793b3 100644 +--- a/gcc/config/riscv/predicates.md ++++ b/gcc/config/riscv/predicates.md +@@ -35,6 +35,10 @@ + (ior (match_operand 0 "const_csr_operand") + (match_operand 0 "register_operand"))) + ++(define_predicate "csr_address" ++ (and (match_code "const_int") ++ (match_test "IN_RANGE (INTVAL (op), 0, IMM_REACH-1)"))) ++ + (define_predicate "sle_operand" + (and (match_code "const_int") + (match_test "SMALL_OPERAND (INTVAL (op) + 1)"))) +diff --git a/gcc/config/riscv/riscv.c b/gcc/config/riscv/riscv.c +index e7440f39095..d90715cca23 100644 +--- a/gcc/config/riscv/riscv.c ++++ b/gcc/config/riscv/riscv.c +@@ -139,6 +139,12 @@ struct GTY(()) machine_function { + bool interrupt_handler_p; + /* For an interrupt handler, indicates the privilege level. */ + enum riscv_privilege_levels interrupt_mode; ++ /* True if current function is an SiFive CLIC preemptible interrupt ++ function. */ ++ bool sifive_clic_preemptible_p; ++ /* True if current function is an SiFive CLIC stack swap interrupt ++ function. */ ++ bool sifive_clic_stack_swap_p; + + /* True if attributes on current function have been checked. */ + bool attributes_checked_p; +@@ -326,7 +332,7 @@ static const struct attribute_spec riscv_attribute_table[] = + { "naked", 0, 0, true, false, false, false, + riscv_handle_fndecl_attribute, NULL }, + /* This attribute generates prologue/epilogue for interrupt handlers. */ +- { "interrupt", 0, 1, false, true, true, false, ++ { "interrupt", 0, 2, false, true, true, false, + riscv_handle_type_attribute, NULL }, + + /* The last attribute spec is set to be NULL. */ +@@ -2813,7 +2819,7 @@ riscv_handle_type_attribute (tree *node ATTRIBUTE_UNUSED, tree name, tree args, + /* Check for an argument. */ + if (is_attribute_p ("interrupt", name)) + { +- if (args) ++ while (args != NULL) + { + tree cst = TREE_VALUE (args); + const char *string; +@@ -2829,14 +2835,18 @@ riscv_handle_type_attribute (tree *node ATTRIBUTE_UNUSED, tree name, tree args, + + string = TREE_STRING_POINTER (cst); + if (strcmp (string, "user") && strcmp (string, "supervisor") +- && strcmp (string, "machine")) ++ && strcmp (string, "machine") ++ && strcmp (string, "SiFive-CLIC-preemptible") ++ && strcmp (string, "SiFive-CLIC-stack-swap")) + { + warning (OPT_Wattributes, +- "argument to %qE attribute is not \"user\", \"supervisor\", or \"machine\"", +- name); ++ "unrecognized argument to %qE attribute", name); + *no_add_attrs = true; + } ++ args = TREE_CHAIN (args); + } ++ ++ return NULL_TREE; + } + + return NULL_TREE; +@@ -3147,6 +3157,7 @@ riscv_memmodel_needs_release_fence (enum memmodel model) + '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. ++ 'x' Print CONST_INT OP as a CSR register name or as a hex number. + 'i' Print i if the operand is not a register. */ + + static void +@@ -3206,6 +3217,35 @@ riscv_print_operand (FILE *file, rtx op, int letter) + default: + if (letter == 'z' && op == CONST0_RTX (GET_MODE (op))) + fputs (reg_names[GP_REG_FIRST], file); ++ else if (letter == 'x' && GET_CODE (op) == CONST_INT) ++ { ++ unsigned HOST_WIDE_INT reg_num = UINTVAL (op); ++ const char *reg_name = NULL; ++ ++ switch (reg_num) ++ { ++ case MSTATUS_REGNUM: ++ reg_name = "mstatus"; ++ break; ++ case MEPC_REGNUM: ++ reg_name = "mepc"; ++ break; ++ case MCAUSE_REGNUM: ++ reg_name = "mcause"; ++ break; ++ case MSCRATCHI_REGNUM: ++ reg_name = "mscratchi"; ++ break; ++ case MSCRATCHO_REGNUM: ++ reg_name = "mscratcho"; ++ break; ++ } ++ ++ if (reg_name) ++ asm_fprintf (file, "%s", reg_name); ++ else ++ asm_fprintf (file, "0x%wx", reg_num); ++ } + else if (letter && letter != 'z') + output_operand_lossage ("invalid use of '%%%c'", letter); + else +@@ -3505,8 +3545,14 @@ riscv_compute_frame_info (void) + unsigned x_save_size = RISCV_STACK_ALIGN (num_x_saved * UNITS_PER_WORD); + unsigned num_save_restore = 1 + riscv_save_libcall_count (frame->mask); + ++ /* In an SiFive CLIC preemptible interrupt function, we need extra space ++ for the initial saves of S0 and S1. */ ++ if (cfun->machine->sifive_clic_preemptible_p) ++ x_save_size = RISCV_STACK_ALIGN ((num_x_saved + 2) * UNITS_PER_WORD); ++ + /* 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) ++ else if (RISCV_STACK_ALIGN (num_save_restore * UNITS_PER_WORD) ++ == x_save_size) + { + /* Libcall saves/restores 3 registers at once, so we need to + allocate 12 bytes for callee-saved register. */ +@@ -3811,6 +3857,7 @@ riscv_expand_prologue (void) + { + struct riscv_frame_info *frame = &cfun->machine->frame; + HOST_WIDE_INT size = frame->total_size; ++ HOST_WIDE_INT interrupt_size = 0; + unsigned mask = frame->mask; + rtx insn; + +@@ -3834,6 +3881,12 @@ riscv_expand_prologue (void) + REG_NOTES (insn) = dwarf; + } + ++ /* Swap in the stack pointer from the mscratch register. */ ++ if (cfun->machine->sifive_clic_stack_swap_p) ++ emit_insn (gen_riscv_csr_read_write (stack_pointer_rtx, ++ GEN_INT (MSCRATCHI_REGNUM), ++ stack_pointer_rtx)); ++ + /* Save the registers. */ + if ((frame->mask | frame->fmask) != 0) + { +@@ -3844,7 +3897,34 @@ riscv_expand_prologue (void) + GEN_INT (-step1)); + RTX_FRAME_RELATED_P (emit_insn (insn)) = 1; + size -= step1; +- riscv_for_each_saved_reg (size, riscv_save_reg, false, false); ++ ++ if (cfun->machine->sifive_clic_preemptible_p) ++ { ++ /* Save S0 and S1. */ ++ riscv_save_restore_reg (word_mode, S0_REGNUM, ++ step1 - (1 * UNITS_PER_WORD), ++ riscv_save_reg); ++ riscv_save_restore_reg (word_mode, S1_REGNUM, ++ step1 - (2 * UNITS_PER_WORD), ++ riscv_save_reg); ++ /* Account for the stack size used by interrupt register saving. */ ++ interrupt_size = 2 * UNITS_PER_WORD; ++ ++ /* Load cause into s0. */ ++ emit_insn (gen_riscv_csr_read (gen_rtx_REG (word_mode, S0_REGNUM), ++ GEN_INT (MCAUSE_REGNUM))); ++ /* Load epc into s1. */ ++ emit_insn (gen_riscv_csr_read (gen_rtx_REG (word_mode, S1_REGNUM), ++ GEN_INT (MEPC_REGNUM))); ++ /* Re-enable interrupts. */ ++ emit_insn (gen_riscv_csr_read_set_bits (gen_rtx_REG (word_mode, ++ GP_REG_FIRST), ++ GEN_INT (MSTATUS_REGNUM), ++ GEN_INT (MSTATUS_MIE_BIT))); ++ } ++ ++ riscv_for_each_saved_reg (size + interrupt_size, riscv_save_reg, ++ false, false); + } + + frame->mask = mask; /* Undo the above fib. */ +@@ -3852,6 +3932,10 @@ riscv_expand_prologue (void) + /* Set up the frame pointer, if we're using one. */ + if (frame_pointer_needed) + { ++ if (cfun->machine->sifive_clic_preemptible_p) ++ error ("SiFive CLIC preemptible %qs function cannot use a frame pointer", ++ "interrupt"); ++ + insn = gen_add3_insn (hard_frame_pointer_rtx, stack_pointer_rtx, + GEN_INT (frame->hard_frame_pointer_offset - size)); + RTX_FRAME_RELATED_P (emit_insn (insn)) = 1; +@@ -3921,6 +4005,7 @@ riscv_expand_epilogue (int style) + unsigned mask = frame->mask; + HOST_WIDE_INT step1 = frame->total_size; + HOST_WIDE_INT step2 = 0; ++ HOST_WIDE_INT interrupt_size = 0; + bool use_restore_libcall = ((style == NORMAL_RETURN) + && riscv_use_save_libcall (frame)); + rtx ra = gen_rtx_REG (Pmode, RETURN_ADDR_REGNUM); +@@ -4021,10 +4106,13 @@ riscv_expand_epilogue (int style) + + if (use_restore_libcall) + frame->mask = 0; /* Temporarily fib that we need not save GPRs. */ ++ else if (cfun->machine->sifive_clic_preemptible_p) ++ interrupt_size = 2 * UNITS_PER_WORD; + + /* Restore the registers. */ +- riscv_for_each_saved_reg (frame->total_size - step2, riscv_restore_reg, +- true, style == EXCEPTION_RETURN); ++ riscv_for_each_saved_reg (frame->total_size - step2 + interrupt_size, ++ riscv_restore_reg, true, ++ style == EXCEPTION_RETURN); + + if (use_restore_libcall) + { +@@ -4032,6 +4120,29 @@ riscv_expand_epilogue (int style) + gcc_assert (step2 >= frame->save_libcall_adjustment); + step2 -= frame->save_libcall_adjustment; + } ++ else if (cfun->machine->sifive_clic_preemptible_p ++ && (frame->mask | frame->fmask) != 0) ++ { ++ /* Disable interrupts. */ ++ emit_insn (gen_riscv_csr_read_clear_bits (gen_rtx_REG (word_mode, ++ GP_REG_FIRST), ++ GEN_INT (MSTATUS_REGNUM), ++ GEN_INT (MSTATUS_MIE_BIT))); ++ /* Save s1 back into mepc. */ ++ emit_insn (gen_riscv_csr_write (GEN_INT (MEPC_REGNUM), ++ gen_rtx_REG (word_mode, S1_REGNUM))); ++ /* Save s0 back into mcause. */ ++ emit_insn (gen_riscv_csr_write (GEN_INT (MCAUSE_REGNUM), ++ gen_rtx_REG (word_mode, S0_REGNUM))); ++ ++ /* Restore S0 and S1. */ ++ riscv_save_restore_reg (word_mode, S1_REGNUM, ++ step2 - (2 * UNITS_PER_WORD), ++ riscv_restore_reg); ++ riscv_save_restore_reg (word_mode, S0_REGNUM, ++ step2 - (1 * UNITS_PER_WORD), ++ riscv_restore_reg); ++ } + + if (need_barrier_p) + riscv_emit_stack_tie (); +@@ -4051,6 +4162,12 @@ riscv_expand_epilogue (int style) + REG_NOTES (insn) = dwarf; + } + ++ /* Swap out the stack opinter from the mscratch register. */ ++ if (cfun->machine->sifive_clic_stack_swap_p) ++ emit_insn (gen_riscv_csr_read_write (stack_pointer_rtx, ++ GEN_INT (MSCRATCHO_REGNUM), ++ stack_pointer_rtx)); ++ + if (use_restore_libcall) + { + rtx dwarf = riscv_adjust_libcall_cfi_epilogue (); +@@ -4738,7 +4855,8 @@ riscv_function_ok_for_sibcall (tree decl ATTRIBUTE_UNUSED, + + /* Get the interrupt type, return UNKNOWN_MODE if it's not + interrupt function. */ +-static enum riscv_privilege_levels ++/* ??? HACK ??? */ ++static void + riscv_get_interrupt_type (tree decl) + { + gcc_assert (decl != NULL_TREE); +@@ -4751,20 +4869,37 @@ riscv_get_interrupt_type (tree decl) + = TREE_VALUE (lookup_attribute ("interrupt", + TYPE_ATTRIBUTES (TREE_TYPE (decl)))); + +- if (attr_args && TREE_CODE (TREE_VALUE (attr_args)) != VOID_TYPE) ++ bool interrupt_mode_set = FALSE; ++ ++ /* Interrupt attributes are machine mode by default. */ ++ cfun->machine->interrupt_mode = MACHINE_MODE; ++ ++ while (attr_args) + { + const char *string = TREE_STRING_POINTER (TREE_VALUE (attr_args)); + +- if (!strcmp (string, "user")) +- return USER_MODE; +- else if (!strcmp (string, "supervisor")) +- return SUPERVISOR_MODE; +- else /* Must be "machine". */ +- return MACHINE_MODE; ++ if (!strcmp (string, "SiFive-CLIC-preemptible")) ++ cfun->machine->sifive_clic_preemptible_p = TRUE; ++ else if (!strcmp (string, "SiFive-CLIC-stack-swap")) ++ cfun->machine->sifive_clic_stack_swap_p = TRUE; ++ else ++ { ++ if (interrupt_mode_set) ++ error ("%qs function cannot have two modes", "interrupt"); ++ interrupt_mode_set = TRUE; ++ ++ if (!strcmp (string, "user")) ++ cfun->machine->interrupt_mode = USER_MODE; ++ else if (!strcmp (string, "supervisor")) ++ cfun->machine->interrupt_mode = SUPERVISOR_MODE; ++ else if (!strcmp (string, "machine")) ++ cfun->machine->interrupt_mode = MACHINE_MODE; ++ else ++ abort (); ++ } ++ ++ attr_args = TREE_CHAIN (attr_args); + } +- else +- /* Interrupt attributes are machine mode by default. */ +- return MACHINE_MODE; + } + + /* Implement `TARGET_SET_CURRENT_FUNCTION'. */ +@@ -4798,7 +4933,17 @@ riscv_set_current_function (tree decl) + if (args && TREE_CODE (TREE_VALUE (args)) != VOID_TYPE) + error ("%qs function cannot have arguments", "interrupt"); + +- cfun->machine->interrupt_mode = riscv_get_interrupt_type (decl); ++ riscv_get_interrupt_type (decl); ++ ++ if (cfun->machine->interrupt_mode != MACHINE_MODE) ++ { ++ if (cfun->machine->sifive_clic_preemptible_p) ++ error ("SiFive CLIC preemptible %qs function must be machine mode", ++ "interrupt"); ++ else if (cfun->machine->sifive_clic_stack_swap_p) ++ error ("SiFive CLIC stack-swap %qs function must be machine mode", ++ "interrupt"); ++ } + + gcc_assert (cfun->machine->interrupt_mode != UNKNOWN_MODE); + } +@@ -4807,6 +4952,8 @@ riscv_set_current_function (tree decl) + cfun->machine->attributes_checked_p = 1; + } + ++#if 0 ++/* ??? HACK ??? */ + /* Implement TARGET_MERGE_DECL_ATTRIBUTES. */ + static tree + riscv_merge_decl_attributes (tree olddecl, tree newdecl) +@@ -4830,6 +4977,7 @@ riscv_merge_decl_attributes (tree olddecl, tree newdecl) + + return combined_attrs; + } ++#endif + + /* Implement TARGET_CANNOT_COPY_INSN_P. */ + +@@ -5027,8 +5175,11 @@ riscv_constant_alignment (const_tree exp, HOST_WIDE_INT align) + #undef TARGET_CONSTANT_ALIGNMENT + #define TARGET_CONSTANT_ALIGNMENT riscv_constant_alignment + ++#if 0 ++/* ??? HACK ??? */ + #undef TARGET_MERGE_DECL_ATTRIBUTES + #define TARGET_MERGE_DECL_ATTRIBUTES riscv_merge_decl_attributes ++#endif + + #undef TARGET_ATTRIBUTE_TABLE + #define TARGET_ATTRIBUTE_TABLE riscv_attribute_table +diff --git a/gcc/config/riscv/riscv.md b/gcc/config/riscv/riscv.md +index e3799a5bdd8..3b7d4f92c1c 100644 +--- a/gcc/config/riscv/riscv.md ++++ b/gcc/config/riscv/riscv.md +@@ -56,6 +56,17 @@ + UNSPECV_FRFLAGS + UNSPECV_FSFLAGS + ++ ;; CSR read ++ UNSPECV_CSR_READ ++ ;; CSR read and set bits ++ UNSPECV_CSR_READ_SET_BITS ++ ;; CSR read and clear bits ++ UNSPECV_CSR_READ_CLEAR_BITS ++ ;; CSR read and write ++ UNSPECV_CSR_READ_WRITE ++ ;; CSR write ++ UNSPECV_CSR_WRITE ++ + ;; Interrupt handler instructions. + UNSPECV_MRET + UNSPECV_SRET +@@ -79,6 +90,14 @@ + (NORMAL_RETURN 0) + (SIBCALL_RETURN 1) + (EXCEPTION_RETURN 2) ++ ++ (MSTATUS_REGNUM 0x300) ++ (MEPC_REGNUM 0x341) ++ (MCAUSE_REGNUM 0x342) ++ (MSCRATCHI_REGNUM 0x348) ++ (MSCRATCHO_REGNUM 0x349) ++ ++ (MSTATUS_MIE_BIT 8) + ]) + + (include "predicates.md") +@@ -2400,6 +2419,44 @@ + "TARGET_HARD_FLOAT" + "fsflags\t%0") + ++(define_insn "riscv_csr_read" ++ [(set (match_operand 0 "register_operand" "=r") ++ (unspec_volatile [(match_operand 1 "csr_address" "C")] ++ UNSPECV_CSR_READ))] ++ "" ++ "csrr\t%0,%x1") ++ ++(define_insn "riscv_csr_read_set_bits" ++ [(set (match_operand 0 "register_operand" "=r") ++ (unspec_volatile [(match_operand 1 "csr_address" "C") ++ (match_operand 2 "csr_operand" "rK")] ++ UNSPECV_CSR_READ_SET_BITS))] ++ "" ++ "csrrsi\t%0,%x1,%2") ++ ++(define_insn "riscv_csr_read_clear_bits" ++ [(set (match_operand 0 "register_operand" "=r") ++ (unspec_volatile [(match_operand 1 "csr_address" "C") ++ (match_operand 2 "csr_operand" "rK")] ++ UNSPECV_CSR_READ_CLEAR_BITS))] ++ "" ++ "csrrci\t%0,%x1,%2") ++ ++(define_insn "riscv_csr_read_write" ++ [(set (match_operand 0 "register_operand" "=r") ++ (unspec_volatile [(match_operand 1 "csr_address" "C") ++ (match_operand 2 "csr_operand" "rK")] ++ UNSPECV_CSR_READ_WRITE))] ++ "" ++ "csrrw\t%0,%x1,%2") ++ ++(define_insn "riscv_csr_write" ++ [(unspec_volatile [(match_operand 0 "csr_address" "C") ++ (match_operand 1 "register_operand" "r")] ++ UNSPECV_CSR_WRITE)] ++ "" ++ "csrw\t%x0,%1") ++ + (define_insn "riscv_mret" + [(return) + (unspec_volatile [(const_int 0)] UNSPECV_MRET)] +diff --git a/gcc/doc/extend.texi b/gcc/doc/extend.texi +index 91679e8b9ba..883db8894db 100644 +--- a/gcc/doc/extend.texi ++++ b/gcc/doc/extend.texi +@@ -5592,6 +5592,31 @@ void f (void) __attribute__ ((interrupt ("user"))); + Permissible values for this parameter are @code{user}, @code{supervisor}, + and @code{machine}. If there is no parameter, then it defaults to + @code{machine}. ++ ++You can specify an SiFive CLIC preemptible interrupt handler by adding an ++optional parameter to the interrupt attribute like this: ++ ++@smallexample ++void f (void) __attribute__ ((interrupt ("SiFive-CLIC-preemptible"))); ++@end smallexample ++ ++In this type of interrupt handler, in the prologue, the mepc and ++mcause registers are saved, and interrupts are enabled. In the epilogue, ++interrupts are disabled, and the mepc and mcause registers are restored. ++This type of interrupt handler must be @code{machine} mode, and must ++not use the frame pointer. ++ ++You can specify an SiFive CLIC stack swapping interrupt handler by adding an ++optional parameter to the interrupt attribute like this: ++ ++@smallexample ++void f (void) __attribute__ ((interrupt ("SiFive-CLIC-stack-swap"))); ++@end smallexample ++ ++In this type of interrupt handler, the stack pointer will be swapped with ++the @code{mscratch} register in the prologue before the first use of the stack ++pointer, and in the epilogue after the last use of the stack pointer. This ++type of interrupt handler must be @code{machine} mode. + @end table + + @node RL78 Function Attributes +diff --git a/gcc/doc/md.texi b/gcc/doc/md.texi +index 30612a6aecb..3783bb25314 100644 +--- a/gcc/doc/md.texi ++++ b/gcc/doc/md.texi +@@ -3577,6 +3577,9 @@ Integer zero. + @item K + A 5-bit unsigned immediate for CSR access instructions. + ++@item C ++A 12-bit unsigned immediate for CSR register address. ++ + @item A + An address that is held in a general-purpose register. + +diff --git a/gcc/testsuite/gcc.target/riscv/interrupt-5.c b/gcc/testsuite/gcc.target/riscv/interrupt-5.c +index 324954eb1dd..03d8173e5b3 100644 +--- a/gcc/testsuite/gcc.target/riscv/interrupt-5.c ++++ b/gcc/testsuite/gcc.target/riscv/interrupt-5.c +@@ -19,3 +19,18 @@ void __attribute__ ((interrupt ("hypervisor"))) + sub3 (void) + { /* { dg-warning "argument to" } */ + } ++ ++void __attribute__ ((interrupt ("user", "machine"))) ++sub4 (void) ++{ /* { dg-error "cannot have two modes" } */ ++} ++ ++void __attribute__ ((interrupt ("user", "SiFive-CLIC-preemptible"))) ++sub5 (void) ++{ /* { dg-error "must be machine mode" } */ ++} ++ ++void __attribute__ ((interrupt ("user", "SiFive-CLIC-stack-swap"))) ++sub6 (void) ++{ /* { dg-error "must be machine mode" } */ ++} +diff --git a/gcc/testsuite/gcc.target/riscv/preemptible-1.c b/gcc/testsuite/gcc.target/riscv/preemptible-1.c +new file mode 100644 +index 00000000000..578667f46cd +--- /dev/null ++++ b/gcc/testsuite/gcc.target/riscv/preemptible-1.c +@@ -0,0 +1,11 @@ ++/* Verify that csr instructions emitted. */ ++/* { dg-do compile } */ ++/* { dg-options "-O" } */ ++extern int interrupt_count; ++ ++void __attribute__ ((interrupt ("SiFive-CLIC-preemptible"))) ++sub (void) ++{ ++ interrupt_count++; ++} ++/* { dg-final { scan-assembler-times "csr" 6 } } */ +diff --git a/gcc/testsuite/gcc.target/riscv/preemptible-2.c b/gcc/testsuite/gcc.target/riscv/preemptible-2.c +new file mode 100644 +index 00000000000..27cd31de188 +--- /dev/null ++++ b/gcc/testsuite/gcc.target/riscv/preemptible-2.c +@@ -0,0 +1,11 @@ ++/* Verify that all temp regs saved for call. */ ++/* { dg-do compile } */ ++/* { dg-options "-O" } */ ++extern int vector_10 (void); ++ ++void __attribute__ ((interrupt ("SiFive-CLIC-preemptible"))) ++sub (void) ++{ ++ vector_10 (); ++} ++/* { dg-final { scan-assembler-times "s\[wd\]\t\[at\]\[0-7\]" 15 } } */ +diff --git a/gcc/testsuite/gcc.target/riscv/preemptible-3.c b/gcc/testsuite/gcc.target/riscv/preemptible-3.c +new file mode 100644 +index 00000000000..c01d9ded7d5 +--- /dev/null ++++ b/gcc/testsuite/gcc.target/riscv/preemptible-3.c +@@ -0,0 +1,9 @@ ++/* Verify that csr instructions are not emitted. */ ++/* { dg-do compile } */ ++/* { dg-options "-O" } */ ++ ++void __attribute__ ((interrupt ("SiFive-CLIC-preemptible"))) ++sub (void) ++{ ++} ++/* { dg-final { scan-assembler-not "csr" } } */ +diff --git a/gcc/testsuite/gcc.target/riscv/stack-swap-1.c b/gcc/testsuite/gcc.target/riscv/stack-swap-1.c +new file mode 100644 +index 00000000000..2e26432cd89 +--- /dev/null ++++ b/gcc/testsuite/gcc.target/riscv/stack-swap-1.c +@@ -0,0 +1,18 @@ ++/* Verify that stack swapping instructions are emitted. */ ++/* { dg-do compile } */ ++/* { dg-options "-O" } */ ++void __attribute__ ((interrupt ("SiFive-CLIC-stack-swap"))) ++foo2 (void) ++{ ++ extern volatile int INTERRUPT_FLAG; ++ INTERRUPT_FLAG = 0; ++ ++ extern volatile int COUNTER; ++#ifdef __riscv_atomic ++ __atomic_fetch_add (&COUNTER, 1, __ATOMIC_RELAXED); ++#else ++ COUNTER++; ++#endif ++} ++/* { dg-final { scan-assembler "mscratchi" } } */ ++/* { dg-final { scan-assembler "mscratcho" } } */ +-- +2.21.0 + diff --git a/0002-Finish-CLIC-support-resolving-patch-merge-error-and-.patch b/0002-Finish-CLIC-support-resolving-patch-merge-error-and-.patch new file mode 100644 index 000000000000..a0e97bb56d49 --- /dev/null +++ b/0002-Finish-CLIC-support-resolving-patch-merge-error-and-.patch @@ -0,0 +1,360 @@ +From 96fded3b45d93f306e86d9529b8ae3ff7f012088 Mon Sep 17 00:00:00 2001 +From: Jim Wilson <jimw@sifive.com> +Date: Thu, 28 Feb 2019 12:09:52 -0800 +Subject: [PATCH 2/3] Finish CLIC support, resolving patch merge error and + adding missing patch. + +--- + gcc/config/riscv/riscv.c | 124 ++++++++++-------- + gcc/config/riscv/riscv.md | 3 +- + .../riscv/interrupt-conflict-mode.c | 2 +- + gcc/testsuite/gcc.target/riscv/stack-swap-1.c | 3 +- + 4 files changed, 69 insertions(+), 63 deletions(-) + +diff --git a/gcc/config/riscv/riscv.c b/gcc/config/riscv/riscv.c +index d90715cca23..0dcfec1974d 100644 +--- a/gcc/config/riscv/riscv.c ++++ b/gcc/config/riscv/riscv.c +@@ -96,7 +96,7 @@ enum riscv_address_type { + }; + + /* Information about a function's frame layout. */ +-struct GTY(()) riscv_frame_info { ++struct GTY(()) riscv_frame_info { + /* The size of the frame in bytes. */ + HOST_WIDE_INT total_size; + +@@ -127,7 +127,18 @@ enum riscv_privilege_levels { + UNKNOWN_MODE, USER_MODE, SUPERVISOR_MODE, MACHINE_MODE + }; + +-struct GTY(()) machine_function { ++struct GTY(()) riscv_interrupt_flags { ++ /* For an interrupt handler, indicates the privilege level. */ ++ enum riscv_privilege_levels interrupt_mode : 2; ++ /* True if current function is an SiFive CLIC preemptible interrupt ++ function. */ ++ bool sifive_clic_preemptible_p : 1; ++ /* True if current function is an SiFive CLIC stack swap interrupt ++ function. */ ++ bool sifive_clic_stack_swap_p : 1; ++}; ++ ++struct GTY(()) machine_function { + /* The number of extra stack bytes taken up by register varargs. + This area is allocated by the callee at the very top of the frame. */ + int varargs_size; +@@ -137,14 +148,8 @@ struct GTY(()) machine_function { + + /* True if current function is an interrupt function. */ + bool interrupt_handler_p; +- /* For an interrupt handler, indicates the privilege level. */ +- enum riscv_privilege_levels interrupt_mode; +- /* True if current function is an SiFive CLIC preemptible interrupt +- function. */ +- bool sifive_clic_preemptible_p; +- /* True if current function is an SiFive CLIC stack swap interrupt +- function. */ +- bool sifive_clic_stack_swap_p; ++ /* For an interrupt handler, hold various argument flag bits. */ ++ struct riscv_interrupt_flags interrupt_flags; + + /* True if attributes on current function have been checked. */ + bool attributes_checked_p; +@@ -3233,11 +3238,8 @@ riscv_print_operand (FILE *file, rtx op, int letter) + case MCAUSE_REGNUM: + reg_name = "mcause"; + break; +- case MSCRATCHI_REGNUM: +- reg_name = "mscratchi"; +- break; +- case MSCRATCHO_REGNUM: +- reg_name = "mscratcho"; ++ case MSCRATCHCSW_REGNUM: ++ reg_name = "mscratchcsw"; + break; + } + +@@ -3547,7 +3549,7 @@ riscv_compute_frame_info (void) + + /* In an SiFive CLIC preemptible interrupt function, we need extra space + for the initial saves of S0 and S1. */ +- if (cfun->machine->sifive_clic_preemptible_p) ++ if (cfun->machine->interrupt_flags.sifive_clic_preemptible_p) + x_save_size = RISCV_STACK_ALIGN ((num_x_saved + 2) * UNITS_PER_WORD); + + /* Only use save/restore routines if they don't alter the stack size. */ +@@ -3882,9 +3884,9 @@ riscv_expand_prologue (void) + } + + /* Swap in the stack pointer from the mscratch register. */ +- if (cfun->machine->sifive_clic_stack_swap_p) ++ if (cfun->machine->interrupt_flags.sifive_clic_stack_swap_p) + emit_insn (gen_riscv_csr_read_write (stack_pointer_rtx, +- GEN_INT (MSCRATCHI_REGNUM), ++ GEN_INT (MSCRATCHCSW_REGNUM), + stack_pointer_rtx)); + + /* Save the registers. */ +@@ -3898,7 +3900,7 @@ riscv_expand_prologue (void) + RTX_FRAME_RELATED_P (emit_insn (insn)) = 1; + size -= step1; + +- if (cfun->machine->sifive_clic_preemptible_p) ++ if (cfun->machine->interrupt_flags.sifive_clic_preemptible_p) + { + /* Save S0 and S1. */ + riscv_save_restore_reg (word_mode, S0_REGNUM, +@@ -3932,7 +3934,7 @@ riscv_expand_prologue (void) + /* Set up the frame pointer, if we're using one. */ + if (frame_pointer_needed) + { +- if (cfun->machine->sifive_clic_preemptible_p) ++ if (cfun->machine->interrupt_flags.sifive_clic_preemptible_p) + error ("SiFive CLIC preemptible %qs function cannot use a frame pointer", + "interrupt"); + +@@ -4106,7 +4108,7 @@ riscv_expand_epilogue (int style) + + if (use_restore_libcall) + frame->mask = 0; /* Temporarily fib that we need not save GPRs. */ +- else if (cfun->machine->sifive_clic_preemptible_p) ++ else if (cfun->machine->interrupt_flags.sifive_clic_preemptible_p) + interrupt_size = 2 * UNITS_PER_WORD; + + /* Restore the registers. */ +@@ -4120,7 +4122,7 @@ riscv_expand_epilogue (int style) + gcc_assert (step2 >= frame->save_libcall_adjustment); + step2 -= frame->save_libcall_adjustment; + } +- else if (cfun->machine->sifive_clic_preemptible_p ++ else if (cfun->machine->interrupt_flags.sifive_clic_preemptible_p + && (frame->mask | frame->fmask) != 0) + { + /* Disable interrupts. */ +@@ -4135,7 +4137,7 @@ riscv_expand_epilogue (int style) + emit_insn (gen_riscv_csr_write (GEN_INT (MCAUSE_REGNUM), + gen_rtx_REG (word_mode, S0_REGNUM))); + +- /* Restore S0 and S1. */ ++ /* Restore S0 and S1. */ + riscv_save_restore_reg (word_mode, S1_REGNUM, + step2 - (2 * UNITS_PER_WORD), + riscv_restore_reg); +@@ -4162,10 +4164,10 @@ riscv_expand_epilogue (int style) + REG_NOTES (insn) = dwarf; + } + +- /* Swap out the stack opinter from the mscratch register. */ +- if (cfun->machine->sifive_clic_stack_swap_p) ++ /* Swap out the stack pointer from the mscratch register. */ ++ if (cfun->machine->interrupt_flags.sifive_clic_stack_swap_p) + emit_insn (gen_riscv_csr_read_write (stack_pointer_rtx, +- GEN_INT (MSCRATCHO_REGNUM), ++ GEN_INT (MSCRATCHCSW_REGNUM), + stack_pointer_rtx)); + + if (use_restore_libcall) +@@ -4187,7 +4189,8 @@ riscv_expand_epilogue (int style) + /* Return from interrupt. */ + if (cfun->machine->interrupt_handler_p) + { +- enum riscv_privilege_levels mode = cfun->machine->interrupt_mode; ++ enum riscv_privilege_levels mode ++ = cfun->machine->interrupt_flags.interrupt_mode; + + gcc_assert (mode != UNKNOWN_MODE); + +@@ -4853,35 +4856,41 @@ riscv_function_ok_for_sibcall (tree decl ATTRIBUTE_UNUSED, + return true; + } + +-/* Get the interrupt type, return UNKNOWN_MODE if it's not ++/* Get the interrupt type, return UNKNOWN_MODE if it's not an + interrupt function. */ +-/* ??? HACK ??? */ +-static void ++static struct riscv_interrupt_flags + riscv_get_interrupt_type (tree decl) + { ++ struct riscv_interrupt_flags interrupt_flags; ++ bool interrupt_mode_set; ++ + gcc_assert (decl != NULL_TREE); + + if ((TREE_CODE(decl) != FUNCTION_DECL) + || (!riscv_interrupt_type_p (TREE_TYPE (decl)))) +- return UNKNOWN_MODE; ++ { ++ interrupt_flags.interrupt_mode = UNKNOWN_MODE; ++ return interrupt_flags; ++ } + + tree attr_args + = TREE_VALUE (lookup_attribute ("interrupt", + TYPE_ATTRIBUTES (TREE_TYPE (decl)))); + +- bool interrupt_mode_set = FALSE; +- + /* Interrupt attributes are machine mode by default. */ +- cfun->machine->interrupt_mode = MACHINE_MODE; ++ interrupt_flags.interrupt_mode = MACHINE_MODE; ++ interrupt_flags.sifive_clic_preemptible_p = FALSE; ++ interrupt_flags.sifive_clic_stack_swap_p = FALSE; ++ interrupt_mode_set = FALSE; + + while (attr_args) + { + const char *string = TREE_STRING_POINTER (TREE_VALUE (attr_args)); + + if (!strcmp (string, "SiFive-CLIC-preemptible")) +- cfun->machine->sifive_clic_preemptible_p = TRUE; ++ interrupt_flags.sifive_clic_preemptible_p = TRUE; + else if (!strcmp (string, "SiFive-CLIC-stack-swap")) +- cfun->machine->sifive_clic_stack_swap_p = TRUE; ++ interrupt_flags.sifive_clic_stack_swap_p = TRUE; + else + { + if (interrupt_mode_set) +@@ -4889,17 +4898,20 @@ riscv_get_interrupt_type (tree decl) + interrupt_mode_set = TRUE; + + if (!strcmp (string, "user")) +- cfun->machine->interrupt_mode = USER_MODE; ++ interrupt_flags.interrupt_mode = USER_MODE; + else if (!strcmp (string, "supervisor")) +- cfun->machine->interrupt_mode = SUPERVISOR_MODE; ++ interrupt_flags.interrupt_mode = SUPERVISOR_MODE; + else if (!strcmp (string, "machine")) +- cfun->machine->interrupt_mode = MACHINE_MODE; ++ interrupt_flags.interrupt_mode = MACHINE_MODE; + else ++ /* Unreachable. Checked in riscv_handle_type_attribute. */ + abort (); + } + + attr_args = TREE_CHAIN (attr_args); + } ++ ++ return interrupt_flags; + } + + /* Implement `TARGET_SET_CURRENT_FUNCTION'. */ +@@ -4933,43 +4945,43 @@ riscv_set_current_function (tree decl) + if (args && TREE_CODE (TREE_VALUE (args)) != VOID_TYPE) + error ("%qs function cannot have arguments", "interrupt"); + +- riscv_get_interrupt_type (decl); ++ cfun->machine->interrupt_flags = riscv_get_interrupt_type (decl); + +- if (cfun->machine->interrupt_mode != MACHINE_MODE) ++ if (cfun->machine->interrupt_flags.interrupt_mode != MACHINE_MODE) + { +- if (cfun->machine->sifive_clic_preemptible_p) ++ if (cfun->machine->interrupt_flags.sifive_clic_preemptible_p) + error ("SiFive CLIC preemptible %qs function must be machine mode", + "interrupt"); +- else if (cfun->machine->sifive_clic_stack_swap_p) ++ else if (cfun->machine->interrupt_flags.sifive_clic_stack_swap_p) + error ("SiFive CLIC stack-swap %qs function must be machine mode", + "interrupt"); + } + +- gcc_assert (cfun->machine->interrupt_mode != UNKNOWN_MODE); ++ gcc_assert (cfun->machine->interrupt_flags.interrupt_mode ++ != UNKNOWN_MODE); + } + + /* Don't print the above diagnostics more than once. */ + cfun->machine->attributes_checked_p = 1; + } + +-#if 0 +-/* ??? HACK ??? */ +-/* Implement TARGET_MERGE_DECL_ATTRIBUTES. */ ++/* Implement TARGET_MERGE_DECL_ATTRIBUTES. */ + static tree + riscv_merge_decl_attributes (tree olddecl, tree newdecl) + { + tree combined_attrs; + +- enum riscv_privilege_levels old_interrupt_type ++ struct riscv_interrupt_flags old_interrupt_type + = riscv_get_interrupt_type (olddecl); +- enum riscv_privilege_levels new_interrupt_type ++ struct riscv_interrupt_flags new_interrupt_type + = riscv_get_interrupt_type (newdecl); + +- /* Check old and new has same interrupt type. */ +- if ((old_interrupt_type != UNKNOWN_MODE) +- && (new_interrupt_type != UNKNOWN_MODE) +- && (old_interrupt_type != new_interrupt_type)) +- error ("%qs function cannot have different interrupt type", "interrupt"); ++ /* Check old and new have same interrupt type. */ ++ if ((old_interrupt_type.interrupt_mode != UNKNOWN_MODE) ++ && (new_interrupt_type.interrupt_mode != UNKNOWN_MODE) ++ && (old_interrupt_type.interrupt_mode ++ != new_interrupt_type.interrupt_mode)) ++ error ("%qs function cannot have different interrupt type.", "interrupt"); + + /* Create combined attributes. */ + combined_attrs = merge_attributes (DECL_ATTRIBUTES (olddecl), +@@ -4977,7 +4989,6 @@ riscv_merge_decl_attributes (tree olddecl, tree newdecl) + + return combined_attrs; + } +-#endif + + /* Implement TARGET_CANNOT_COPY_INSN_P. */ + +@@ -5175,11 +5186,8 @@ riscv_constant_alignment (const_tree exp, HOST_WIDE_INT align) + #undef TARGET_CONSTANT_ALIGNMENT + #define TARGET_CONSTANT_ALIGNMENT riscv_constant_alignment + +-#if 0 +-/* ??? HACK ??? */ + #undef TARGET_MERGE_DECL_ATTRIBUTES + #define TARGET_MERGE_DECL_ATTRIBUTES riscv_merge_decl_attributes +-#endif + + #undef TARGET_ATTRIBUTE_TABLE + #define TARGET_ATTRIBUTE_TABLE riscv_attribute_table +diff --git a/gcc/config/riscv/riscv.md b/gcc/config/riscv/riscv.md +index 3b7d4f92c1c..a27e921d5a9 100644 +--- a/gcc/config/riscv/riscv.md ++++ b/gcc/config/riscv/riscv.md +@@ -94,8 +94,7 @@ + (MSTATUS_REGNUM 0x300) + (MEPC_REGNUM 0x341) + (MCAUSE_REGNUM 0x342) +- (MSCRATCHI_REGNUM 0x348) +- (MSCRATCHO_REGNUM 0x349) ++ (MSCRATCHCSW_REGNUM 0x348) + + (MSTATUS_MIE_BIT 8) + ]) +diff --git a/gcc/testsuite/gcc.target/riscv/interrupt-conflict-mode.c b/gcc/testsuite/gcc.target/riscv/interrupt-conflict-mode.c +index e9f145265c0..793397feaf4 100644 +--- a/gcc/testsuite/gcc.target/riscv/interrupt-conflict-mode.c ++++ b/gcc/testsuite/gcc.target/riscv/interrupt-conflict-mode.c +@@ -6,5 +6,5 @@ foo(void); + + void __attribute__ ((interrupt ("machine"))) + foo (void) +-{ /* { dg-error "function cannot have different interrupt type" } */ ++{ /* { dg-error "function cannot have different interrupt type." } */ + } +diff --git a/gcc/testsuite/gcc.target/riscv/stack-swap-1.c b/gcc/testsuite/gcc.target/riscv/stack-swap-1.c +index 2e26432cd89..bbc89b58e18 100644 +--- a/gcc/testsuite/gcc.target/riscv/stack-swap-1.c ++++ b/gcc/testsuite/gcc.target/riscv/stack-swap-1.c +@@ -14,5 +14,4 @@ foo2 (void) + COUNTER++; + #endif + } +-/* { dg-final { scan-assembler "mscratchi" } } */ +-/* { dg-final { scan-assembler "mscratcho" } } */ ++/* { dg-final { scan-assembler-times "mscratchcsw" 2 } } */ +-- +2.21.0 + diff --git a/0003-RISC-V-Add-short-forward-branch-optimization-for-sif.patch b/0003-RISC-V-Add-short-forward-branch-optimization-for-sif.patch new file mode 100644 index 000000000000..79b85dd7503b --- /dev/null +++ b/0003-RISC-V-Add-short-forward-branch-optimization-for-sif.patch @@ -0,0 +1,284 @@ +From 17fc91857ce3d7ec5f4755c616aa4598c6daa783 Mon Sep 17 00:00:00 2001 +From: Jim Wilson <jimw@sifive.com> +Date: Thu, 4 Apr 2019 08:34:32 -0700 +Subject: [PATCH 3/3] RISC-V: Add short-forward-branch optimization for + sifive-7 core. + + gcc/ + * config/riscv/constraints.md (L): New. + * config/riscv/predicates.md (lui_operand): New. + (sfb_alu_operand): New. + * config/riscv/riscv-protos.h (riscv_expand_conditional_move): Declare. + * config/riscv/riscv.c (riscv_expand_conditional_move): New. + (riscv_print_operand): Add support for 'w' and 'y'. Update comment. + * config/riscv/riscv.h (TARGET_SFB_ALU): New. + * config/riscv/riscv.md (type): Add sfb_alu. + (branch_order<mode>, branch_zero<mode>): Delete. + (branch<mode>): New, combined from the two deleted patterns. + (mov<mode>cc, mov<GPR:mode><X:mode>cc): New, using TARGET_SFB_ALU. + * config/riscv/sifive-7.md: Update bypasses for sfb alu support. + (sifive_7_sfb_alu): New. +--- + gcc/config/riscv/constraints.md | 5 ++++ + gcc/config/riscv/predicates.md | 8 +++++ + gcc/config/riscv/riscv-protos.h | 1 + + gcc/config/riscv/riscv.c | 28 +++++++++++++++-- + gcc/config/riscv/riscv.h | 11 +++++++ + gcc/config/riscv/riscv.md | 53 +++++++++++++++++++++++---------- + gcc/config/riscv/sifive-7.md | 12 ++++++-- + 7 files changed, 97 insertions(+), 21 deletions(-) + +diff --git a/gcc/config/riscv/constraints.md b/gcc/config/riscv/constraints.md +index a736013d9f6..96d09e6a313 100644 +--- a/gcc/config/riscv/constraints.md ++++ b/gcc/config/riscv/constraints.md +@@ -54,6 +54,11 @@ + (and (match_code "const_int") + (match_test "IN_RANGE (ival, 0, IMM_REACH-1)"))) + ++(define_constraint "L" ++ "A U-type 20-bit signed immediate." ++ (and (match_code "const_int") ++ (match_test "LUI_OPERAND (ival)"))) ++ + ;; Floating-point constant +0.0, used for FCVT-based moves when FMV is + ;; not available in RV32. + (define_constraint "G" +diff --git a/gcc/config/riscv/predicates.md b/gcc/config/riscv/predicates.md +index 83e698793b3..655713bdcbf 100644 +--- a/gcc/config/riscv/predicates.md ++++ b/gcc/config/riscv/predicates.md +@@ -27,6 +27,14 @@ + (ior (match_operand 0 "const_arith_operand") + (match_operand 0 "register_operand"))) + ++(define_predicate "lui_operand" ++ (and (match_code "const_int") ++ (match_test "LUI_OPERAND (INTVAL (op))"))) ++ ++(define_predicate "sfb_alu_operand" ++ (ior (match_operand 0 "arith_operand") ++ (match_operand 0 "lui_operand"))) ++ + (define_predicate "const_csr_operand" + (and (match_code "const_int") + (match_test "IN_RANGE (INTVAL (op), 0, 31)"))) +diff --git a/gcc/config/riscv/riscv-protos.h b/gcc/config/riscv/riscv-protos.h +index 8b510f87df8..612188f76fb 100644 +--- a/gcc/config/riscv/riscv-protos.h ++++ b/gcc/config/riscv/riscv-protos.h +@@ -59,6 +59,7 @@ extern const char *riscv_output_return (); + extern void riscv_expand_int_scc (rtx, enum rtx_code, rtx, rtx); + extern void riscv_expand_float_scc (rtx, enum rtx_code, rtx, rtx); + extern void riscv_expand_conditional_branch (rtx, enum rtx_code, rtx, rtx); ++extern void riscv_expand_conditional_move (rtx, rtx, rtx, rtx_code, rtx, rtx); + #endif + extern rtx riscv_legitimize_call_address (rtx); + extern void riscv_set_return_address (rtx, rtx); +diff --git a/gcc/config/riscv/riscv.c b/gcc/config/riscv/riscv.c +index 0dcfec1974d..105b42c7264 100644 +--- a/gcc/config/riscv/riscv.c ++++ b/gcc/config/riscv/riscv.c +@@ -2307,6 +2307,18 @@ riscv_expand_conditional_branch (rtx label, rtx_code code, rtx op0, rtx op1) + emit_jump_insn (gen_condjump (condition, label)); + } + ++/* If (CODE OP0 OP1) holds, move CONS to DEST; else move ALT to DEST. */ ++ ++void ++riscv_expand_conditional_move (rtx dest, rtx cons, rtx alt, rtx_code code, ++ rtx op0, rtx op1) ++{ ++ riscv_emit_int_compare (&code, &op0, &op1); ++ rtx cond = gen_rtx_fmt_ee (code, GET_MODE (op0), op0, op1); ++ emit_insn (gen_rtx_SET (dest, gen_rtx_IF_THEN_ELSE (GET_MODE (dest), cond, ++ cons, alt))); ++} ++ + /* Implement TARGET_FUNCTION_ARG_BOUNDARY. Every parameter gets at + least PARM_BOUNDARY bits of alignment, but will be given anything up + to PREFERRED_STACK_BOUNDARY bits if the type requires it. */ +@@ -3161,6 +3173,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. ++ 'w' Print nothing if OP is zero, otherwise print OP followed by a comma. ++ 'y' Print 'z' if OP is zero, otherwise print nothing. + 'z' Print x0 if OP is zero, otherwise print OP normally. + 'x' Print CONST_INT OP as a CSR register name or as a hex number. + 'i' Print i if the operand is not a register. */ +@@ -3207,9 +3221,13 @@ riscv_print_operand (FILE *file, rtx op, int letter) + switch (code) + { + case REG: +- if (letter && letter != 'z') ++ if (letter && letter == 'y') ++ break; ++ else if (letter && letter != 'w' && letter != 'z') + output_operand_lossage ("invalid use of '%%%c'", letter); + fprintf (file, "%s", reg_names[REGNO (op)]); ++ if (letter == 'w') ++ fputs(",", file); + break; + + case MEM: +@@ -3220,7 +3238,11 @@ riscv_print_operand (FILE *file, rtx op, int letter) + break; + + default: +- if (letter == 'z' && op == CONST0_RTX (GET_MODE (op))) ++ if (letter == 'w') ++ break; ++ else if (letter == 'y' && op == CONST0_RTX (GET_MODE (op))) ++ fputs ("z", file); ++ else if (letter == 'z' && op == CONST0_RTX (GET_MODE (op))) + fputs (reg_names[GP_REG_FIRST], file); + else if (letter == 'x' && GET_CODE (op) == CONST_INT) + { +@@ -3248,7 +3270,7 @@ riscv_print_operand (FILE *file, rtx op, int letter) + else + asm_fprintf (file, "0x%wx", reg_num); + } +- else if (letter && letter != 'z') ++ else if (letter && letter != 'y' && letter != 'z') + output_operand_lossage ("invalid use of '%%%c'", letter); + else + output_addr_const (file, riscv_strip_unspec_address (op)); +diff --git a/gcc/config/riscv/riscv.h b/gcc/config/riscv/riscv.h +index c93743f9549..4edd2a60194 100644 +--- a/gcc/config/riscv/riscv.h ++++ b/gcc/config/riscv/riscv.h +@@ -662,6 +662,17 @@ typedef struct { + #define BRANCH_COST(speed_p, predictable_p) \ + ((!(speed_p) || (predictable_p)) ? 2 : riscv_branch_cost) + ++/* True if the target optimizes short forward branches around integer ++ arithmetic instructions into predicated operations, e.g., for ++ conditional-move operations. The macro assumes that all branch ++ instructions (BEQ, BNE, BLT, BLTU, BGE, BGEU, C.BEQZ, and C.BNEZ) ++ support this feature. The macro further assumes that any integer ++ arithmetic and logical operation (ADD[I], SUB, SLL[I], SRL[I], SRA[I], ++ SLT[I][U], AND[I], XOR[I], OR[I], LUI, AUIPC, and their compressed ++ counterparts, including C.MV and C.LI) can be in the branch shadow. */ ++ ++#define TARGET_SFB_ALU (riscv_microarchitecture == sifive_7) ++ + #define LOGICAL_OP_NON_SHORT_CIRCUIT 0 + + /* Control the assembler format that we output. */ +diff --git a/gcc/config/riscv/riscv.md b/gcc/config/riscv/riscv.md +index a27e921d5a9..22ede6d8478 100644 +--- a/gcc/config/riscv/riscv.md ++++ b/gcc/config/riscv/riscv.md +@@ -174,7 +174,7 @@ + (define_attr "type" + "unknown,branch,jump,call,load,fpload,store,fpstore, + mtc,mfc,const,arith,logical,shift,slt,imul,idiv,move,fmove,fadd,fmul, +- fmadd,fdiv,fcmp,fcvt,fsqrt,multi,auipc,nop,ghost" ++ fmadd,fdiv,fcmp,fcvt,fsqrt,multi,auipc,sfb_alu,nop,ghost" + (cond [(eq_attr "got" "load") (const_string "load") + + ;; If a doubleword move uses these expensive instructions, +@@ -1821,31 +1821,52 @@ + + ;; Conditional branches + +-(define_insn "*branch_order<mode>" ++(define_insn "*branch<mode>" + [(set (pc) + (if_then_else + (match_operator 1 "order_operator" + [(match_operand:X 2 "register_operand" "r") +- (match_operand:X 3 "register_operand" "r")]) ++ (match_operand:X 3 "reg_or_0_operand" "rJ")]) + (label_ref (match_operand 0 "" "")) + (pc)))] + "" +- "b%C1\t%2,%3,%0" ++ "b%C1%y3\t%2,%w3%0" + [(set_attr "type" "branch") + (set_attr "mode" "none")]) + +-(define_insn "*branch_zero<mode>" +- [(set (pc) +- (if_then_else +- (match_operator 1 "signed_order_operator" +- [(match_operand:X 2 "register_operand" "r") +- (const_int 0)]) +- (label_ref (match_operand 0 "" "")) +- (pc)))] +- "" +- "b%C1z\t%2,%0" +- [(set_attr "type" "branch") +- (set_attr "mode" "none")]) ++;; Patterns for implementations that optimize short forward branches ++ ++(define_expand "mov<mode>cc" ++ [(set (match_operand:GPR 0 "register_operand") ++ (if_then_else:GPR (match_operand 1 "comparison_operator") ++ (match_operand:GPR 2 "register_operand") ++ (match_operand:GPR 3 "sfb_alu_operand")))] ++ "TARGET_SFB_ALU" ++{ ++ rtx cmp = operands[1]; ++ /* We only handle word mode integer compares for now. */ ++ if (GET_MODE (XEXP (cmp, 0)) != word_mode) ++ FAIL; ++ riscv_expand_conditional_move (operands[0], operands[2], operands[3], ++ GET_CODE (cmp), XEXP (cmp, 0), XEXP (cmp, 1)); ++ DONE; ++}) ++ ++(define_insn "*mov<GPR:mode><X:mode>cc" ++ [(set (match_operand:GPR 0 "register_operand" "=r,r") ++ (if_then_else:GPR ++ (match_operator 5 "order_operator" ++ [(match_operand:X 1 "register_operand" "r,r") ++ (match_operand:X 2 "reg_or_0_operand" "rJ,rJ")]) ++ (match_operand:GPR 3 "register_operand" "0,0") ++ (match_operand:GPR 4 "sfb_alu_operand" "rJ,IL")))] ++ "TARGET_SFB_ALU" ++ "@ ++ b%C5%y2 %1, %w2 1f; mv %0, %z4; 1: # movcc ++ b%C5%y2 %1, %w2 1f; li %0, %4; 1: # movcc" ++ [(set_attr "length" "8") ++ (set_attr "type" "sfb_alu") ++ (set_attr "mode" "<GPR:MODE>")]) + + ;; Used to implement built-in functions. + (define_expand "condjump" +diff --git a/gcc/config/riscv/sifive-7.md b/gcc/config/riscv/sifive-7.md +index d58e01f8936..526278e46d4 100644 +--- a/gcc/config/riscv/sifive-7.md ++++ b/gcc/config/riscv/sifive-7.md +@@ -37,6 +37,11 @@ + (eq_attr "type" "branch")) + "sifive_7_B") + ++(define_insn_reservation "sifive_7_sfb_alu" 2 ++ (and (eq_attr "tune" "sifive_7") ++ (eq_attr "type" "sfb_alu")) ++ "sifive_7_A+sifive_7_B") ++ + (define_insn_reservation "sifive_7_jump" 1 + (and (eq_attr "tune" "sifive_7") + (eq_attr "type" "jump,call")) +@@ -101,10 +106,13 @@ + (eq_attr "type" "mfc")) + "sifive_7_A") + +-(define_bypass 1 "sifive_7_load,sifive_7_alu,sifive_7_mul,sifive_7_f2i" ++(define_bypass 1 "sifive_7_load,sifive_7_alu,sifive_7_mul,sifive_7_f2i,sifive_7_sfb_alu" + "sifive_7_alu,sifive_7_branch") + +-(define_bypass 1 "sifive_7_load,sifive_7_alu,sifive_7_mul,sifive_7_f2i" ++(define_bypass 1 "sifive_7_alu,sifive_7_sfb_alu" ++ "sifive_7_sfb_alu") ++ ++(define_bypass 1 "sifive_7_load,sifive_7_alu,sifive_7_mul,sifive_7_f2i,sifive_7_sfb_alu" + "sifive_7_store" "riscv_store_data_bypass_p") + + (define_bypass 2 "sifive_7_i2f" +-- +2.21.0 + diff --git a/0004-Remove-libgloss.patch b/0004-Remove-libgloss.patch new file mode 100644 index 000000000000..b7febd4e7218 --- /dev/null +++ b/0004-Remove-libgloss.patch @@ -0,0 +1,17 @@ +diff --git a/gcc/config/riscv/elf.h b/gcc/config/riscv/elf.h +index 9be97b866..8a0df0a37 100644 +--- a/gcc/config/riscv/elf.h ++++ b/gcc/config/riscv/elf.h +@@ -22,10 +22,9 @@ along with GCC; see the file COPYING3. If not see + %{mno-relax:--no-relax} \ + %{shared}" + +-/* Link against Newlib libraries, because the ELF backend assumes Newlib. +- Handle the circular dependence between libc and libgloss. */ ++/* remove the dependency of libgloss, no default libc. */ + #undef LIB_SPEC +-#define LIB_SPEC "--start-group -lc %{!specs=nosys.specs:-lgloss} --end-group" ++#define LIB_SPEC "--start-group -lgcc -lg -lc --end-group" + + #undef STARTFILE_SPEC + #define STARTFILE_SPEC "crt0%O%s crtbegin%O%s" diff --git a/PKGBUILD b/PKGBUILD new file mode 100644 index 000000000000..0d5ed468e168 --- /dev/null +++ b/PKGBUILD @@ -0,0 +1,97 @@ +# Maintainer: Jiuyang Liu <liujiuyang1994@gmail.com> + +# Follow the upstream of https://github.com/sifive/freedom-tools/blob/master/Makefile + +_target=riscv-sifive-elf +pkgname=$_target-gcc-stage1 +pkgver=9.1.0 +pkgrel=1 +pkgdesc='Cross compiler for 32-bit and 64-bit RISC-V' +arch=('x86_64') +url='https://gcc.gnu.org/' +license=('GPL' 'LGPL' 'FDL') +groups=('risc-v') +depends=("$_target-binutils" "libmpc") +options=('!emptydirs' '!strip') +makedepends=('python') +source=("https://gcc.gnu.org/pub/gcc/releases/gcc-$pkgver/gcc-$pkgver.tar.xz" + "0001-SiFive-CLIC-patches-for-preemptible-and-stack-swappi.patch" + "0002-Finish-CLIC-support-resolving-patch-merge-error-and-.patch" + "0003-RISC-V-Add-short-forward-branch-optimization-for-sif.patch" + "0004-Remove-libgloss.patch") +md5sums=('6069ae3737cf02bf2cb44a391ef0e937' + 'SKIP' + 'SKIP' + 'SKIP' + 'SKIP') + +prepare() { + # hack! - some configure tests for header files using "$CPP $CPPFLAGS" + sed -i "/ac_cpp=/s/\$CPPFLAGS/\$CPPFLAGS -O2/" \ + "$srcdir/gcc-$pkgver/"{libiberty,gcc}/configure + + rm -rf "$srcdir/gcc-build" + mkdir "$srcdir/gcc-build" + export GCC_MULTILIB="rv32e-ilp32e--c rv32em-ilp32e--c rv32eac-ilp32e-- rv32emac-ilp32e-- rv32i-ilp32--c rv32im-ilp32--c rv32iac-ilp32-- rv32imac-ilp32-- rv32imaf-ilp32f-- rv32imafc-ilp32f-rv32imafdc- rv32imafdc-ilp32d-- rv64imac-lp64-- rv64imafc-lp64f-rv64imafdc- rv64imafdc-lp64d--" + IFS=$' ' + cd $srcdir/gcc-$pkgver/gcc/config/riscv/ + ./multilib-generator $GCC_MULTILIB > t-elf-multilib + cd $srcdir/gcc-$pkgver + echo "patch unmerged work from SiFive." + patch --forward --strip=1 --input="${srcdir}/0001-SiFive-CLIC-patches-for-preemptible-and-stack-swappi.patch" + patch --forward --strip=1 --input="${srcdir}/0002-Finish-CLIC-support-resolving-patch-merge-error-and-.patch" + patch --forward --strip=1 --input="${srcdir}/0003-RISC-V-Add-short-forward-branch-optimization-for-sif.patch" + patch --forward --strip=1 --input="${srcdir}/0004-Remove-libgloss.patch" +} + +build() { + cd gcc-build + + # https://github.com/sifive/freedom-tools/blob/master/Makefile#L274 include c and c++ support in stage1, I removed this. + "$srcdir/gcc-$pkgver/configure" \ + --disable-libgomp \ + --disable-libmudflap \ + --disable-libquadmath \ + --disable-libssp \ + --disable-nls \ + --disable-shared \ + --disable-threads \ + --disable-tls \ + --enable-checking=yes \ + --enable-languages=c \ + --enable-multilib \ + --libexecdir=/usr/lib \ + --prefix=/usr \ + --target=$_target \ + --with-abi="ilp32" \ + --with-arch="rv32imac" \ + --with-bugurl='https://bugs.archlinux.org/' \ + --with-newlib \ + --with-pkgversion='Arch Repository' \ + --with-python-dir=share/gcc-riscv-sifive-elf \ + --with-sysroot=/usr/$_target \ + --with-system-zlib \ + CFLAGS="-O2" \ + CXXFLAGS="-O2" \ + CFLAGS_FOR_TARGET="-Os -mcmodel=medany" \ + CXXFLAGS_FOR_TARGET="-Os -mcmodel=medany" + + make +} + +package() { + make -C gcc-build DESTDIR="$pkgdir" install-gcc install-target-libgcc + + # Strip target binaries + find "$pkgdir/usr/lib/gcc/$_target/" -type f \ + -and \( -name \*.a -or -name \*.o \) -exec $_target-objcopy \ + -R .comment -R .note -R .debug_info -R .debug_aranges -R .debug_pubnames \ + -R .debug_pubtypes -R .debug_abbrev -R .debug_line -R .debug_str \ + -R .debug_ranges -R .debug_loc '{}' \; + + # Strip host binaries + find "$pkgdir/usr/bin/" "$pkgdir/usr/lib/gcc/$_target/" -type f \ + -and \( -executable \) -exec strip '{}' \; + # Remove files that conflict with host gcc package + rm -r "$pkgdir/usr/share/"{man/man7,info} +} |