From f767aec04c93291e3a3b3c7eff20e039cc3cc0ad Mon Sep 17 00:00:00 2001 From: Max Filippov Date: Mon, 10 Nov 2014 17:36:50 +0300 Subject: [PATCH] local-patches: sync with xtensa gcc call0 ABI support Fixed: - possible a7/a15 corruption in functions with 6+ argument words and frame pointer enabled; - vararg functions; - setjmp/longjmp; - nested functions; - profiling with -pg option (_mcount call); A bit improved code generation for SP manipulations. Known broken: - __builtin_return_address; - __builtin_frame_address for frames other than current. Unknown: - C++ exception handling. Signed-off-by: Max Filippov --- ...IP-xtensa-fix-lib-code-for-call0-ABI.patch | 2 +- .../0002-WIP-xtensa-implement-call0-ABI.patch | 2 +- ...plement-callee-saved-register-saving.patch | 2 +- ...emit-.literal_position-for-call0-ABI.patch | 2 +- ...3-instead-of-addsi3-in-call0-prologu.patch | 2 +- ...ess-with-argument-in-a7-in-CALL0-ABI.patch | 48 +++ ...ct-guards-on-CRT_CALL_STATIC_FUNCTIO.patch | 37 ++ ...ee-saved-register-check-to-xtensa_ca.patch | 70 ++++ ...tensa-fix-_mcount-call-for-CALL0-ABI.patch | 56 +++ ...lace-if-ifdef-with-if-where-possible.patch | 376 ++++++++++++++++++ ...e-default-nonlocal_goto-in-CALL0-ABI.patch | 82 ++++ ...ow-direct-loading-of-sp-in-CALL0-ABI.patch | 52 +++ ...trampolines-generation-for-CALL0-ABI.patch | 232 +++++++++++ ...ial-cases-for-SP-in-machine-definiti.patch | 159 ++++++++ ...-fix-addsi3-pattern-for-windowed-ABI.patch | 26 ++ ...nge-entry-pattern-in-machine-descrip.patch | 29 ++ 16 files changed, 1172 insertions(+), 5 deletions(-) create mode 100644 local-patches/gcc/4.8.2/0006-xtensa-don-t-mess-with-argument-in-a7-in-CALL0-ABI.patch create mode 100644 local-patches/gcc/4.8.2/0007-xtensa-use-correct-guards-on-CRT_CALL_STATIC_FUNCTIO.patch create mode 100644 local-patches/gcc/4.8.2/0008-xtensa-move-callee-saved-register-check-to-xtensa_ca.patch create mode 100644 local-patches/gcc/4.8.2/0009-WIP-xtensa-fix-_mcount-call-for-CALL0-ABI.patch create mode 100644 local-patches/gcc/4.8.2/0010-xtensa-replace-if-ifdef-with-if-where-possible.patch create mode 100644 local-patches/gcc/4.8.2/0011-xtensa-use-default-nonlocal_goto-in-CALL0-ABI.patch create mode 100644 local-patches/gcc/4.8.2/0012-xtensa-allow-direct-loading-of-sp-in-CALL0-ABI.patch create mode 100644 local-patches/gcc/4.8.2/0013-xtensa-fix-trampolines-generation-for-CALL0-ABI.patch create mode 100644 local-patches/gcc/4.8.2/0014-xtensa-drop-special-cases-for-SP-in-machine-definiti.patch create mode 100644 local-patches/gcc/4.8.2/0015-xtensa-fix-addsi3-pattern-for-windowed-ABI.patch create mode 100644 local-patches/gcc/4.8.2/0016-xtensa-don-t-change-entry-pattern-in-machine-descrip.patch diff --git a/local-patches/gcc/4.8.2/0001-WIP-xtensa-fix-lib-code-for-call0-ABI.patch b/local-patches/gcc/4.8.2/0001-WIP-xtensa-fix-lib-code-for-call0-ABI.patch index dbfb765f4..b2622e0eb 100644 --- a/local-patches/gcc/4.8.2/0001-WIP-xtensa-fix-lib-code-for-call0-ABI.patch +++ b/local-patches/gcc/4.8.2/0001-WIP-xtensa-fix-lib-code-for-call0-ABI.patch @@ -1,7 +1,7 @@ From 676b5a725bd71c9deb72b1957a5e6cf892d5d9fb Mon Sep 17 00:00:00 2001 From: Max Filippov Date: Sun, 14 Sep 2014 21:15:14 -0700 -Subject: [PATCH 1/3] WIP: xtensa: fix lib code for call0 ABI +Subject: [PATCH 01/16] WIP: xtensa: fix lib code for call0 ABI Signed-off-by: Max Filippov --- diff --git a/local-patches/gcc/4.8.2/0002-WIP-xtensa-implement-call0-ABI.patch b/local-patches/gcc/4.8.2/0002-WIP-xtensa-implement-call0-ABI.patch index 3ac52cd7e..1231f3abc 100644 --- a/local-patches/gcc/4.8.2/0002-WIP-xtensa-implement-call0-ABI.patch +++ b/local-patches/gcc/4.8.2/0002-WIP-xtensa-implement-call0-ABI.patch @@ -1,7 +1,7 @@ From 06d069d40208c4ce7456920e8b4f571ac9511821 Mon Sep 17 00:00:00 2001 From: Max Filippov Date: Sun, 14 Sep 2014 16:43:27 -0700 -Subject: [PATCH 2/3] WIP: xtensa: implement call0 ABI +Subject: [PATCH 02/16] WIP: xtensa: implement call0 ABI Signed-off-by: Max Filippov --- diff --git a/local-patches/gcc/4.8.2/0003-WIP-xtensa-implement-callee-saved-register-saving.patch b/local-patches/gcc/4.8.2/0003-WIP-xtensa-implement-callee-saved-register-saving.patch index a2a18fc0c..51ea8aa2f 100644 --- a/local-patches/gcc/4.8.2/0003-WIP-xtensa-implement-callee-saved-register-saving.patch +++ b/local-patches/gcc/4.8.2/0003-WIP-xtensa-implement-callee-saved-register-saving.patch @@ -1,7 +1,7 @@ From d82c531991bb31e864e05f02032187f2e9dbc66f Mon Sep 17 00:00:00 2001 From: Max Filippov Date: Sun, 28 Sep 2014 22:52:01 +0400 -Subject: [PATCH 3/3] WIP: xtensa: implement callee-saved register saving +Subject: [PATCH 03/16] WIP: xtensa: implement callee-saved register saving Also fix frame pointer, correctly move stack pointer, and avoid movsp. diff --git a/local-patches/gcc/4.8.2/0004-xtensa-always-emit-.literal_position-for-call0-ABI.patch b/local-patches/gcc/4.8.2/0004-xtensa-always-emit-.literal_position-for-call0-ABI.patch index 69556be45..78d559c5f 100644 --- a/local-patches/gcc/4.8.2/0004-xtensa-always-emit-.literal_position-for-call0-ABI.patch +++ b/local-patches/gcc/4.8.2/0004-xtensa-always-emit-.literal_position-for-call0-ABI.patch @@ -1,7 +1,7 @@ From 0b74cbfbbf3aa9b67f1c9f1971e98b0980b10661 Mon Sep 17 00:00:00 2001 From: Max Filippov Date: Sun, 5 Oct 2014 05:54:31 +0400 -Subject: [PATCH 4/5] xtensa: always emit .literal_position for call0 ABI +Subject: [PATCH 04/16] xtensa: always emit .literal_position for call0 ABI xtensa assembler implicitly starts literal pool before entry instructions. Emit .literal_position at the beginning of function for diff --git a/local-patches/gcc/4.8.2/0005-xtensa-use-subsi3-instead-of-addsi3-in-call0-prologu.patch b/local-patches/gcc/4.8.2/0005-xtensa-use-subsi3-instead-of-addsi3-in-call0-prologu.patch index 2200ca8b5..562fe2eca 100644 --- a/local-patches/gcc/4.8.2/0005-xtensa-use-subsi3-instead-of-addsi3-in-call0-prologu.patch +++ b/local-patches/gcc/4.8.2/0005-xtensa-use-subsi3-instead-of-addsi3-in-call0-prologu.patch @@ -1,7 +1,7 @@ From 1acaae7db15d0da960cbfd470533a51d8551f7b9 Mon Sep 17 00:00:00 2001 From: Max Filippov Date: Sun, 5 Oct 2014 06:26:18 +0400 -Subject: [PATCH 5/5] xtensa: use subsi3 instead of addsi3 in call0 prologue +Subject: [PATCH 05/16] xtensa: use subsi3 instead of addsi3 in call0 prologue This allows sharing single literal for stack adjustment between prologue and epilogue. diff --git a/local-patches/gcc/4.8.2/0006-xtensa-don-t-mess-with-argument-in-a7-in-CALL0-ABI.patch b/local-patches/gcc/4.8.2/0006-xtensa-don-t-mess-with-argument-in-a7-in-CALL0-ABI.patch new file mode 100644 index 000000000..b2a27c3c0 --- /dev/null +++ b/local-patches/gcc/4.8.2/0006-xtensa-don-t-mess-with-argument-in-a7-in-CALL0-ABI.patch @@ -0,0 +1,48 @@ +From 2d1af52aaa84f8e15a32eeb5ec58868f842a8acc Mon Sep 17 00:00:00 2001 +From: Max Filippov +Date: Sun, 9 Nov 2014 03:48:56 +0300 +Subject: [PATCH 06/16] xtensa: don't mess with argument in a7 in CALL0 ABI + +Otherwise prologue ends with frame pointer in a7 instead of a15. CALL0 +ABI doesn't need this special care because a7 is an ordinary register in +that ABI. + +Signed-off-by: Max Filippov +--- + gcc/config/xtensa/xtensa.c | 8 ++++---- + 1 file changed, 4 insertions(+), 4 deletions(-) + +diff --git a/gcc/config/xtensa/xtensa.c b/gcc/config/xtensa/xtensa.c +index 7a17ea8..29dc603 100644 +--- a/gcc/config/xtensa/xtensa.c ++++ b/gcc/config/xtensa/xtensa.c +@@ -2118,7 +2118,7 @@ xtensa_function_arg_1 (cumulative_args_t cum_v, enum machine_mode mode, + regno = regbase + *arg_words; + + if (cum->incoming && regno <= A7_REG && regno + words > A7_REG) +- cfun->machine->need_a7_copy = true; ++ cfun->machine->need_a7_copy = TARGET_WINDOWED_ABI; + + return gen_rtx_REG (mode, regno); + } +@@ -2957,14 +2957,14 @@ xtensa_builtin_saveregs (void) + set_mem_alias_set (gp_regs, get_varargs_alias_set ()); + + /* Now store the incoming registers. */ +- cfun->machine->need_a7_copy = true; ++ cfun->machine->need_a7_copy = TARGET_WINDOWED_ABI; + cfun->machine->vararg_a7 = true; + move_block_from_reg (GP_ARG_FIRST + arg_words, + adjust_address (gp_regs, BLKmode, + arg_words * UNITS_PER_WORD), + gp_left); +- gcc_assert (cfun->machine->vararg_a7_copy != 0); +- emit_insn_before (cfun->machine->vararg_a7_copy, get_insns ()); ++ if (cfun->machine->vararg_a7_copy != 0) ++ emit_insn_before (cfun->machine->vararg_a7_copy, get_insns ()); + + return XEXP (gp_regs, 0); + } +-- +1.8.1.4 + diff --git a/local-patches/gcc/4.8.2/0007-xtensa-use-correct-guards-on-CRT_CALL_STATIC_FUNCTIO.patch b/local-patches/gcc/4.8.2/0007-xtensa-use-correct-guards-on-CRT_CALL_STATIC_FUNCTIO.patch new file mode 100644 index 000000000..cb727b050 --- /dev/null +++ b/local-patches/gcc/4.8.2/0007-xtensa-use-correct-guards-on-CRT_CALL_STATIC_FUNCTIO.patch @@ -0,0 +1,37 @@ +From b1b4c61a540a146d5f1acb31fa065204b83eb6a4 Mon Sep 17 00:00:00 2001 +From: Max Filippov +Date: Sun, 9 Nov 2014 04:52:36 +0300 +Subject: [PATCH 07/16] xtensa: use correct guards on CRT_CALL_STATIC_FUNCTION + definition + +CRT_CALL_STATIC_FUNCTION is used in libgcc, so it needs to be defined +depending on __XTENSA_*_ABI__, not TARGET_WINDOWED_ABI. + +Signed-off-by: Max Filippov +--- + gcc/config/xtensa/xtensa.h | 4 ++-- + 1 file changed, 2 insertions(+), 2 deletions(-) + +diff --git a/gcc/config/xtensa/xtensa.h b/gcc/config/xtensa/xtensa.h +index 9f4a8a1..f7e22ce 100644 +--- a/gcc/config/xtensa/xtensa.h ++++ b/gcc/config/xtensa/xtensa.h +@@ -880,13 +880,13 @@ typedef struct xtensa_args + a MOVI and let the assembler relax it -- for the .init and .fini + sections, the assembler knows to put the literal in the right + place. */ +-#if TARGET_WINDOWED_ABI ++#if defined(__XTENSA_WINDOWED_ABI__) + #define CRT_CALL_STATIC_FUNCTION(SECTION_OP, FUNC) \ + asm (SECTION_OP "\n\ + movi\ta8, " USER_LABEL_PREFIX #FUNC "\n\ + callx8\ta8\n" \ + TEXT_SECTION_ASM_OP); +-#else ++#elif defined(__XTENSA_CALL0_ABI__) + #define CRT_CALL_STATIC_FUNCTION(SECTION_OP, FUNC) \ + asm (SECTION_OP "\n\ + movi\ta0, " USER_LABEL_PREFIX #FUNC "\n\ +-- +1.8.1.4 + diff --git a/local-patches/gcc/4.8.2/0008-xtensa-move-callee-saved-register-check-to-xtensa_ca.patch b/local-patches/gcc/4.8.2/0008-xtensa-move-callee-saved-register-check-to-xtensa_ca.patch new file mode 100644 index 000000000..3b8356f3c --- /dev/null +++ b/local-patches/gcc/4.8.2/0008-xtensa-move-callee-saved-register-check-to-xtensa_ca.patch @@ -0,0 +1,70 @@ +From 2f60e5db550a287c58e6e69d993946818d01159c Mon Sep 17 00:00:00 2001 +From: Max Filippov +Date: Sun, 9 Nov 2014 06:24:08 +0300 +Subject: [PATCH 08/16] xtensa: move callee-saved register check to + xtensa_call_save_reg + +Don't reserve extra stack space with windowed ABI. Save A0 when +profiling is enabled. + +Signed-off-by: Max Filippov +--- + gcc/config/xtensa/xtensa.c | 21 +++++++++++++++------ + 1 file changed, 15 insertions(+), 6 deletions(-) + +diff --git a/gcc/config/xtensa/xtensa.c b/gcc/config/xtensa/xtensa.c +index 29dc603..e5dc8db 100644 +--- a/gcc/config/xtensa/xtensa.c ++++ b/gcc/config/xtensa/xtensa.c +@@ -2585,6 +2585,18 @@ xtensa_output_literal (FILE *file, rtx x, enum machine_mode mode, int labelno) + } + } + ++static bool ++xtensa_call_save_reg(int regno) ++{ ++ if (TARGET_WINDOWED_ABI) ++ return false; ++ ++ if (regno == A0_REG) ++ return crtl->profile || df_regs_ever_live_p (regno); ++ ++ return !fixed_regs[regno] && !call_used_regs[regno] && ++ df_regs_ever_live_p (regno); ++} + + /* Return the bytes needed to compute the frame pointer from the current + stack pointer. */ +@@ -2604,8 +2616,7 @@ compute_frame_size (int size) + xtensa_callee_save_size = 0; + for (regno = 0; regno < FIRST_PSEUDO_REGISTER; ++regno) + { +- if ((regno == A0_REG || (!fixed_regs[regno] && !call_used_regs[regno])) && +- df_regs_ever_live_p (regno)) ++ if (xtensa_call_save_reg(regno)) + xtensa_callee_save_size += UNITS_PER_WORD; + } + +@@ -2691,8 +2702,7 @@ xtensa_expand_prologue (void) + + for (regno = 0; regno < FIRST_PSEUDO_REGISTER; ++regno) + { +- if ((regno == A0_REG || (!fixed_regs[regno] && !call_used_regs[regno])) && +- df_regs_ever_live_p (regno)) ++ if (xtensa_call_save_reg(regno)) + { + rtx x = gen_rtx_PLUS (Pmode, stack_pointer_rtx, GEN_INT (offset)); + +@@ -2779,8 +2789,7 @@ xtensa_expand_epilogue (void) + + for (regno = 0; regno < FIRST_PSEUDO_REGISTER; ++regno) + { +- if ((regno == A0_REG || (!fixed_regs[regno] && !call_used_regs[regno])) && +- df_regs_ever_live_p (regno)) ++ if (xtensa_call_save_reg(regno)) + { + rtx x = gen_rtx_PLUS (Pmode, stack_pointer_rtx, GEN_INT (offset)); + +-- +1.8.1.4 + diff --git a/local-patches/gcc/4.8.2/0009-WIP-xtensa-fix-_mcount-call-for-CALL0-ABI.patch b/local-patches/gcc/4.8.2/0009-WIP-xtensa-fix-_mcount-call-for-CALL0-ABI.patch new file mode 100644 index 000000000..9550adb04 --- /dev/null +++ b/local-patches/gcc/4.8.2/0009-WIP-xtensa-fix-_mcount-call-for-CALL0-ABI.patch @@ -0,0 +1,56 @@ +From c73b720ae2759c70a4c657962e0bcb40c42fd9bc Mon Sep 17 00:00:00 2001 +From: Max Filippov +Date: Sun, 9 Nov 2014 06:26:29 +0300 +Subject: [PATCH 09/16] WIP: xtensa: fix _mcount call for CALL0 ABI + +_mcount is not specified, let's call it with return address in a10, and +require it to preserve all registers. + +Signed-off-by: Max Filippov +--- + gcc/config/xtensa/xtensa.h | 21 +++------------------ + 1 file changed, 3 insertions(+), 18 deletions(-) + +diff --git a/gcc/config/xtensa/xtensa.h b/gcc/config/xtensa/xtensa.h +index f7e22ce..653631e 100644 +--- a/gcc/config/xtensa/xtensa.h ++++ b/gcc/config/xtensa/xtensa.h +@@ -601,32 +601,17 @@ typedef struct xtensa_args + + #define NO_PROFILE_COUNTERS 1 + +-#if TARGET_WINDOWED_ABI + #define FUNCTION_PROFILER(FILE, LABELNO) \ + do { \ + fprintf (FILE, "\t%s\ta10, a0\n", TARGET_DENSITY ? "mov.n" : "mov"); \ + if (flag_pic) \ + { \ +- fprintf (FILE, "\tmovi\ta8, _mcount@PLT\n"); \ +- fprintf (FILE, "\tcallx8\ta8\n"); \ +- } \ +- else \ +- fprintf (FILE, "\tcall8\t_mcount\n"); \ +- } while (0) +-#else +-#define FUNCTION_PROFILER(FILE, LABELNO) \ +- do { \ +- fprintf (FILE, "\t%s\ta2, a0\n", TARGET_DENSITY ? "mov.n" : "mov"); \ +- /* TODO save incoming args? */ \ +- if (flag_pic) \ +- { \ +- fprintf (FILE, "\tmovi\ta0, _mcount@PLT\n"); \ +- fprintf (FILE, "\tcallx0\ta0\n"); \ ++ fprintf (FILE, "\tmovi\ta%d, _mcount@PLT\n", WINDOW_SIZE); \ ++ fprintf (FILE, "\tcallx%d\ta%d\n", WINDOW_SIZE, WINDOW_SIZE); \ + } \ + else \ +- fprintf (FILE, "\tcall0\t_mcount\n"); \ ++ fprintf (FILE, "\tcall%d\t_mcount\n", WINDOW_SIZE); \ + } while (0) +-#endif + + /* Stack pointer value doesn't matter at exit. */ + #define EXIT_IGNORE_STACK 1 +-- +1.8.1.4 + diff --git a/local-patches/gcc/4.8.2/0010-xtensa-replace-if-ifdef-with-if-where-possible.patch b/local-patches/gcc/4.8.2/0010-xtensa-replace-if-ifdef-with-if-where-possible.patch new file mode 100644 index 000000000..0abc08f45 --- /dev/null +++ b/local-patches/gcc/4.8.2/0010-xtensa-replace-if-ifdef-with-if-where-possible.patch @@ -0,0 +1,376 @@ +From 8fc87fc4ac361effe8903b433a622c339c076a4f Mon Sep 17 00:00:00 2001 +From: Max Filippov +Date: Sun, 9 Nov 2014 06:31:09 +0300 +Subject: [PATCH 10/16] xtensa: replace #if/#ifdef with if where possible + +Signed-off-by: Max Filippov +--- + gcc/config/xtensa/xtensa.c | 279 +++++++++++++++++++++++---------------------- + gcc/config/xtensa/xtensa.h | 13 +-- + 2 files changed, 143 insertions(+), 149 deletions(-) + +diff --git a/gcc/config/xtensa/xtensa.c b/gcc/config/xtensa/xtensa.c +index e5dc8db..f44d9ef 100644 +--- a/gcc/config/xtensa/xtensa.c ++++ b/gcc/config/xtensa/xtensa.c +@@ -1603,11 +1603,10 @@ xtensa_setup_frame_addresses (void) + /* Set flag to cause TARGET_FRAME_POINTER_REQUIRED to return true. */ + cfun->machine->accesses_prev_frame = 1; + +-#if TARGET_WINDOWED_ABI +- emit_library_call +- (gen_rtx_SYMBOL_REF (Pmode, "__xtensa_libgcc_window_spill"), +- LCT_NORMAL, VOIDmode, 0); +-#endif ++ if (TARGET_WINDOWED_ABI) ++ emit_library_call ++ (gen_rtx_SYMBOL_REF (Pmode, "__xtensa_libgcc_window_spill"), ++ LCT_NORMAL, VOIDmode, 0); + } + + +@@ -2659,64 +2658,66 @@ xtensa_expand_prologue (void) + + total_size = compute_frame_size (get_frame_size ()); + +-#if TARGET_WINDOWED_ABI +- +- if (total_size < (1 << (12+3))) +- insn = emit_insn (gen_entry (GEN_INT (total_size))); +- else +- { +- /* Use a8 as a temporary since a0-a7 may be live. */ +- rtx tmp_reg = gen_rtx_REG (Pmode, A8_REG); +- emit_insn (gen_entry (GEN_INT (MIN_FRAME_SIZE))); +- emit_move_insn (tmp_reg, GEN_INT (total_size - MIN_FRAME_SIZE)); +- emit_insn (gen_subsi3 (tmp_reg, stack_pointer_rtx, tmp_reg)); +- insn = emit_insn (gen_movsi (stack_pointer_rtx, tmp_reg)); +- } +-#else +- /* -128 is a limit of single addi instruction. */ +- if (total_size > 0 && total_size <= 128) ++ if (TARGET_WINDOWED_ABI) + { +- insn = emit_insn (gen_addsi3 (stack_pointer_rtx, stack_pointer_rtx, +- GEN_INT (-total_size))); +- offset = total_size - UNITS_PER_WORD; ++ if (total_size < (1 << (12+3))) ++ insn = emit_insn (gen_entry (GEN_INT (total_size))); ++ else ++ { ++ /* Use a8 as a temporary since a0-a7 may be live. */ ++ rtx tmp_reg = gen_rtx_REG (Pmode, A8_REG); ++ emit_insn (gen_entry (GEN_INT (MIN_FRAME_SIZE))); ++ emit_move_insn (tmp_reg, GEN_INT (total_size - MIN_FRAME_SIZE)); ++ emit_insn (gen_subsi3 (tmp_reg, stack_pointer_rtx, tmp_reg)); ++ insn = emit_insn (gen_movsi (stack_pointer_rtx, tmp_reg)); ++ } + } +- else if (xtensa_callee_save_size) ++ else + { +- /* 1020 is maximal s32i offset, if the frame is bigger than that +- * we move sp to the end of callee-saved save area, save and then +- * move it to its final location. */ +- if (total_size > 1024) +- { ++ /* -128 is a limit of single addi instruction. */ ++ if (total_size > 0 && total_size <= 128) ++ { + insn = emit_insn (gen_addsi3 (stack_pointer_rtx, stack_pointer_rtx, +- GEN_INT (-xtensa_callee_save_size))); +- offset = xtensa_callee_save_size - UNITS_PER_WORD; +- } +- else +- { +- rtx tmp_reg = gen_rtx_REG (Pmode, A9_REG); +- emit_move_insn (tmp_reg, GEN_INT (total_size)); +- insn = emit_insn (gen_subsi3 (stack_pointer_rtx, stack_pointer_rtx, tmp_reg)); ++ GEN_INT (-total_size))); + offset = total_size - UNITS_PER_WORD; + } +- } ++ else if (xtensa_callee_save_size) ++ { ++ /* 1020 is maximal s32i offset, if the frame is bigger than that ++ * we move sp to the end of callee-saved save area, save and then ++ * move it to its final location. */ ++ if (total_size > 1024) ++ { ++ insn = emit_insn (gen_addsi3 (stack_pointer_rtx, stack_pointer_rtx, ++ GEN_INT (-xtensa_callee_save_size))); ++ offset = xtensa_callee_save_size - UNITS_PER_WORD; ++ } ++ else ++ { ++ rtx tmp_reg = gen_rtx_REG (Pmode, A9_REG); ++ emit_move_insn (tmp_reg, GEN_INT (total_size)); ++ insn = emit_insn (gen_subsi3 (stack_pointer_rtx, stack_pointer_rtx, tmp_reg)); ++ offset = total_size - UNITS_PER_WORD; ++ } ++ } + +- for (regno = 0; regno < FIRST_PSEUDO_REGISTER; ++regno) +- { +- if (xtensa_call_save_reg(regno)) +- { +- rtx x = gen_rtx_PLUS (Pmode, stack_pointer_rtx, GEN_INT (offset)); ++ for (regno = 0; regno < FIRST_PSEUDO_REGISTER; ++regno) ++ { ++ if (xtensa_call_save_reg(regno)) ++ { ++ rtx x = gen_rtx_PLUS (Pmode, stack_pointer_rtx, GEN_INT (offset)); + +- offset -= UNITS_PER_WORD; +- emit_move_insn (gen_frame_mem (SImode, x), gen_rtx_REG (SImode, regno)); ++ offset -= UNITS_PER_WORD; ++ emit_move_insn (gen_frame_mem (SImode, x), gen_rtx_REG (SImode, regno)); ++ } ++ } ++ if (total_size > 1024) ++ { ++ rtx tmp_reg = gen_rtx_REG (Pmode, A9_REG); ++ emit_move_insn (tmp_reg, GEN_INT (total_size - xtensa_callee_save_size)); ++ insn = emit_insn (gen_subsi3 (stack_pointer_rtx, stack_pointer_rtx, tmp_reg)); + } + } +- if (total_size > 1024) +- { +- rtx tmp_reg = gen_rtx_REG (Pmode, A9_REG); +- emit_move_insn (tmp_reg, GEN_INT (total_size - xtensa_callee_save_size)); +- insn = emit_insn (gen_subsi3 (stack_pointer_rtx, stack_pointer_rtx, tmp_reg)); +- } +-#endif + + if (frame_pointer_needed) + { +@@ -2766,73 +2767,74 @@ xtensa_expand_prologue (void) + void + xtensa_expand_epilogue (void) + { +-#if !TARGET_WINDOWED_ABI +- int regno; +- rtx insn; +- HOST_WIDE_INT offset; +- +- if (xtensa_current_frame_size > (frame_pointer_needed ? 127 : 1024)) ++ if (!TARGET_WINDOWED_ABI) + { +- rtx tmp_reg = gen_rtx_REG (Pmode, A9_REG); +- emit_move_insn (tmp_reg, GEN_INT (xtensa_current_frame_size - +- xtensa_callee_save_size)); +- insn = emit_insn (gen_addsi3 (stack_pointer_rtx, frame_pointer_needed ? +- hard_frame_pointer_rtx : stack_pointer_rtx, tmp_reg)); +- offset = xtensa_callee_save_size - UNITS_PER_WORD; +- } +- else +- { +- if (frame_pointer_needed) +- emit_move_insn (stack_pointer_rtx, hard_frame_pointer_rtx); +- offset = xtensa_current_frame_size - UNITS_PER_WORD; +- } +- +- for (regno = 0; regno < FIRST_PSEUDO_REGISTER; ++regno) +- { +- if (xtensa_call_save_reg(regno)) +- { +- rtx x = gen_rtx_PLUS (Pmode, stack_pointer_rtx, GEN_INT (offset)); ++ int regno; ++ rtx insn; ++ HOST_WIDE_INT offset; + +- offset -= UNITS_PER_WORD; +- emit_move_insn (gen_rtx_REG (SImode, regno), gen_frame_mem (SImode, x)); ++ if (xtensa_current_frame_size > (frame_pointer_needed ? 127 : 1024)) ++ { ++ rtx tmp_reg = gen_rtx_REG (Pmode, A9_REG); ++ emit_move_insn (tmp_reg, GEN_INT (xtensa_current_frame_size - ++ xtensa_callee_save_size)); ++ insn = emit_insn (gen_addsi3 (stack_pointer_rtx, frame_pointer_needed ? ++ hard_frame_pointer_rtx : stack_pointer_rtx, tmp_reg)); ++ offset = xtensa_callee_save_size - UNITS_PER_WORD; ++ } ++ else ++ { ++ if (frame_pointer_needed) ++ emit_move_insn (stack_pointer_rtx, hard_frame_pointer_rtx); ++ offset = xtensa_current_frame_size - UNITS_PER_WORD; + } +- } +- +- if (xtensa_current_frame_size > 0) +- { +- rtx note_rtx; + +- if (frame_pointer_needed || /* always reachable with addi */ +- xtensa_current_frame_size > 1024 || +- xtensa_current_frame_size <= 127) ++ for (regno = 0; regno < FIRST_PSEUDO_REGISTER; ++regno) + { +- if (xtensa_current_frame_size <= 127) +- offset = xtensa_current_frame_size; +- else +- offset = xtensa_callee_save_size; ++ if (xtensa_call_save_reg(regno)) ++ { ++ rtx x = gen_rtx_PLUS (Pmode, stack_pointer_rtx, GEN_INT (offset)); + +- insn = emit_insn (gen_addsi3 (stack_pointer_rtx, stack_pointer_rtx, +- GEN_INT (offset))); ++ offset -= UNITS_PER_WORD; ++ emit_move_insn (gen_rtx_REG (SImode, regno), gen_frame_mem (SImode, x)); ++ } + } +- else ++ ++ if (xtensa_current_frame_size > 0) + { +- rtx tmp_reg = gen_rtx_REG (Pmode, A9_REG); +- emit_move_insn (tmp_reg, GEN_INT (xtensa_current_frame_size)); +- insn = emit_insn (gen_addsi3 (stack_pointer_rtx, stack_pointer_rtx, tmp_reg)); +- } ++ rtx note_rtx; + +- /* Create a note to describe the CFA. Because this is only used to set +- DW_AT_frame_base for debug info, don't bother tracking changes through +- each instruction in the prologue. It just takes up space. */ +- note_rtx = gen_rtx_SET (VOIDmode, stack_pointer_rtx, +- plus_constant (Pmode, frame_pointer_needed +- ? hard_frame_pointer_rtx +- : stack_pointer_rtx, +- xtensa_current_frame_size)); +- RTX_FRAME_RELATED_P (insn) = 1; +- add_reg_note (insn, REG_FRAME_RELATED_EXPR, note_rtx); ++ if (frame_pointer_needed || /* always reachable with addi */ ++ xtensa_current_frame_size > 1024 || ++ xtensa_current_frame_size <= 127) ++ { ++ if (xtensa_current_frame_size <= 127) ++ offset = xtensa_current_frame_size; ++ else ++ offset = xtensa_callee_save_size; ++ ++ insn = emit_insn (gen_addsi3 (stack_pointer_rtx, stack_pointer_rtx, ++ GEN_INT (offset))); ++ } ++ else ++ { ++ rtx tmp_reg = gen_rtx_REG (Pmode, A9_REG); ++ emit_move_insn (tmp_reg, GEN_INT (xtensa_current_frame_size)); ++ insn = emit_insn (gen_addsi3 (stack_pointer_rtx, stack_pointer_rtx, tmp_reg)); ++ } ++ ++ /* Create a note to describe the CFA. Because this is only used to set ++ DW_AT_frame_base for debug info, don't bother tracking changes through ++ each instruction in the prologue. It just takes up space. */ ++ note_rtx = gen_rtx_SET (VOIDmode, stack_pointer_rtx, ++ plus_constant (Pmode, frame_pointer_needed ++ ? hard_frame_pointer_rtx ++ : stack_pointer_rtx, ++ xtensa_current_frame_size)); ++ RTX_FRAME_RELATED_P (insn) = 1; ++ add_reg_note (insn, REG_FRAME_RELATED_EXPR, note_rtx); ++ } + } +-#endif + xtensa_current_frame_size = 0; + xtensa_callee_save_size = 0; + emit_jump_insn (gen_return ()); +@@ -2853,35 +2855,34 @@ xtensa_return_addr (int count, rtx frame) + emit_move_insn (retaddr, gen_rtx_MEM (Pmode, addr)); + } + +-#if TARGET_WINDOWED_ABI +- { +- rtx result, curaddr, label; +- /* The 2 most-significant bits of the return address on Xtensa hold +- the register window size. To get the real return address, these +- bits must be replaced with the high bits from some address in the +- code. */ +- +- /* Get the 2 high bits of a local label in the code. */ +- curaddr = gen_reg_rtx (Pmode); +- label = gen_label_rtx (); +- emit_label (label); +- LABEL_PRESERVE_P (label) = 1; +- emit_move_insn (curaddr, gen_rtx_LABEL_REF (Pmode, label)); +- emit_insn (gen_lshrsi3 (curaddr, curaddr, GEN_INT (30))); +- emit_insn (gen_ashlsi3 (curaddr, curaddr, GEN_INT (30))); +- +- /* Clear the 2 high bits of the return address. */ +- result = gen_reg_rtx (Pmode); +- emit_insn (gen_ashlsi3 (result, retaddr, GEN_INT (2))); +- emit_insn (gen_lshrsi3 (result, result, GEN_INT (2))); +- +- /* Combine them to get the result. */ +- emit_insn (gen_iorsi3 (result, result, curaddr)); +- return result; +- } +-#else +- return retaddr; +-#endif ++ if (TARGET_WINDOWED_ABI) ++ { ++ rtx result, curaddr, label; ++ /* The 2 most-significant bits of the return address on Xtensa hold ++ the register window size. To get the real return address, these ++ bits must be replaced with the high bits from some address in the ++ code. */ ++ ++ /* Get the 2 high bits of a local label in the code. */ ++ curaddr = gen_reg_rtx (Pmode); ++ label = gen_label_rtx (); ++ emit_label (label); ++ LABEL_PRESERVE_P (label) = 1; ++ emit_move_insn (curaddr, gen_rtx_LABEL_REF (Pmode, label)); ++ emit_insn (gen_lshrsi3 (curaddr, curaddr, GEN_INT (30))); ++ emit_insn (gen_ashlsi3 (curaddr, curaddr, GEN_INT (30))); ++ ++ /* Clear the 2 high bits of the return address. */ ++ result = gen_reg_rtx (Pmode); ++ emit_insn (gen_ashlsi3 (result, retaddr, GEN_INT (2))); ++ emit_insn (gen_lshrsi3 (result, result, GEN_INT (2))); ++ ++ /* Combine them to get the result. */ ++ emit_insn (gen_iorsi3 (result, result, curaddr)); ++ return result; ++ } ++ else ++ return retaddr; + } + + /* Disable the use of word-sized or smaller complex modes for structures, +diff --git a/gcc/config/xtensa/xtensa.h b/gcc/config/xtensa/xtensa.h +index 653631e..23374bc 100644 +--- a/gcc/config/xtensa/xtensa.h ++++ b/gcc/config/xtensa/xtensa.h +@@ -358,11 +358,8 @@ extern char xtensa_hard_regno_mode_ok[][FIRST_PSEUDO_REGISTER]; + #define STACK_POINTER_REGNUM (GP_REG_FIRST + 1) + + /* Base register for access to local variables of the function. */ +-#if TARGET_WINDOWED_ABI +-#define HARD_FRAME_POINTER_REGNUM (GP_REG_FIRST + 7) +-#else +-#define HARD_FRAME_POINTER_REGNUM (GP_REG_FIRST + 15) +-#endif ++#define HARD_FRAME_POINTER_REGNUM (GP_REG_FIRST + \ ++ (TARGET_WINDOWED_ABI ? 7 : 15)) + + /* The register number of the frame pointer register, which is used to + access automatic variables in the stack frame. For Xtensa, this +@@ -538,11 +535,7 @@ extern const enum reg_class xtensa_regno_to_class[FIRST_PSEUDO_REGISTER]; + #define STACK_BOUNDARY 128 + + /* Use a fixed register window size of 8. */ +-#if TARGET_WINDOWED_ABI +-#define WINDOW_SIZE 8 +-#else +-#define WINDOW_SIZE 0 +-#endif ++#define WINDOW_SIZE (TARGET_WINDOWED_ABI ? 8 : 0) + + /* Symbolic macros for the registers used to return integer, floating + point, and values of coprocessor and user-defined modes. */ +-- +1.8.1.4 + diff --git a/local-patches/gcc/4.8.2/0011-xtensa-use-default-nonlocal_goto-in-CALL0-ABI.patch b/local-patches/gcc/4.8.2/0011-xtensa-use-default-nonlocal_goto-in-CALL0-ABI.patch new file mode 100644 index 000000000..c2ace6b70 --- /dev/null +++ b/local-patches/gcc/4.8.2/0011-xtensa-use-default-nonlocal_goto-in-CALL0-ABI.patch @@ -0,0 +1,82 @@ +From ffda4ff4764984633e3e88374fa38d97a6bb33a4 Mon Sep 17 00:00:00 2001 +From: Max Filippov +Date: Sun, 9 Nov 2014 23:17:49 +0300 +Subject: [PATCH 11/16] xtensa: use default nonlocal_goto in CALL0 ABI + +CALL0 doesn't need any additional stack modifications, so it can use the +default nonlocal_goto pattern and it doesn't need helper functions to +spill registers and unwind stack. + +Signed-off-by: Max Filippov +--- + gcc/config/xtensa/xtensa.md | 2 +- + libgcc/config/xtensa/lib2funcs.S | 12 ++++-------- + 2 files changed, 5 insertions(+), 9 deletions(-) + +diff --git a/gcc/config/xtensa/xtensa.md b/gcc/config/xtensa/xtensa.md +index 7ddd326..7433b04 100644 +--- a/gcc/config/xtensa/xtensa.md ++++ b/gcc/config/xtensa/xtensa.md +@@ -1655,7 +1655,7 @@ + (match_operand:SI 1 "general_operand" "") + (match_operand:SI 2 "general_operand" "") + (match_operand:SI 3 "" "")] +- "" ++ "TARGET_WINDOWED_ABI" + { + xtensa_expand_nonlocal_goto (operands); + DONE; +diff --git a/libgcc/config/xtensa/lib2funcs.S b/libgcc/config/xtensa/lib2funcs.S +index f6f7a58..aea4449 100644 +--- a/libgcc/config/xtensa/lib2funcs.S ++++ b/libgcc/config/xtensa/lib2funcs.S +@@ -29,19 +29,17 @@ see the files COPYING3 and COPYING.RUNTIME respectively. If not, see + current register window. This is used to set up the stack so that + arbitrary frames can be accessed. */ + ++#if XCHAL_HAVE_WINDOWED && !__XTENSA_CALL0_ABI__ + .align 4 + .global __xtensa_libgcc_window_spill + .type __xtensa_libgcc_window_spill,@function + __xtensa_libgcc_window_spill: +-#if XCHAL_HAVE_WINDOWED && !__XTENSA_CALL0_ABI__ + entry sp, 32 + movi a2, 0 + syscall + retw +-#else +- ret +-#endif + .size __xtensa_libgcc_window_spill, .-__xtensa_libgcc_window_spill ++#endif + + + /* __xtensa_nonlocal_goto: This code does all the hard work of a +@@ -55,11 +53,11 @@ __xtensa_libgcc_window_spill: + This function never returns to its caller but instead goes directly + to the address of the specified goto handler. */ + ++#if XCHAL_HAVE_WINDOWED && !__XTENSA_CALL0_ABI__ + .align 4 + .global __xtensa_nonlocal_goto + .type __xtensa_nonlocal_goto,@function + __xtensa_nonlocal_goto: +-#if XCHAL_HAVE_WINDOWED && !__XTENSA_CALL0_ABI__ + entry sp, 32 + + /* Flush registers. */ +@@ -132,10 +130,8 @@ __xtensa_nonlocal_goto: + src a0, a8, a3 /* combine them with a funnel shift */ + + retw +-#else +- ret +-#endif + .size __xtensa_nonlocal_goto, .-__xtensa_nonlocal_goto ++#endif + + + /* __xtensa_sync_caches: This function is called after writing a trampoline +-- +1.8.1.4 + diff --git a/local-patches/gcc/4.8.2/0012-xtensa-allow-direct-loading-of-sp-in-CALL0-ABI.patch b/local-patches/gcc/4.8.2/0012-xtensa-allow-direct-loading-of-sp-in-CALL0-ABI.patch new file mode 100644 index 000000000..5bfa87f3b --- /dev/null +++ b/local-patches/gcc/4.8.2/0012-xtensa-allow-direct-loading-of-sp-in-CALL0-ABI.patch @@ -0,0 +1,52 @@ +From 73fee6043d8939bc32009771d0ea93eb0bf57643 Mon Sep 17 00:00:00 2001 +From: Max Filippov +Date: Mon, 10 Nov 2014 02:38:42 +0300 +Subject: [PATCH 12/16] xtensa: allow direct loading of sp in CALL0 ABI + +Signed-off-by: Max Filippov +--- + gcc/config/xtensa/xtensa.md | 11 +++++++---- + 1 file changed, 7 insertions(+), 4 deletions(-) + +diff --git a/gcc/config/xtensa/xtensa.md b/gcc/config/xtensa/xtensa.md +index 7433b04..9781080 100644 +--- a/gcc/config/xtensa/xtensa.md ++++ b/gcc/config/xtensa/xtensa.md +@@ -816,14 +816,15 @@ + }) + + (define_insn "movsi_internal" +- [(set (match_operand:SI 0 "nonimmed_operand" "=D,D,D,D,R,R,a,q,q,a,W,a,a,U,*a,*A") +- (match_operand:SI 1 "move_operand" "M,D,d,R,D,d,r,r,r,I,i,T,U,r,*A,*r"))] ++ [(set (match_operand:SI 0 "nonimmed_operand" "=D,D,D,D,d,R,R,a,q,q,a,W,a,a,q,U,*a,*A") ++ (match_operand:SI 1 "move_operand" "M,D,d,R,R,D,d,r,r,r,I,i,T,U,U,r,*A,*r"))] + "xtensa_valid_move (SImode, operands)" + "@ + movi.n\t%0, %x1 + mov.n\t%0, %1 + mov.n\t%0, %1 + %v1l32i.n\t%0, %1 ++ %v1l32i.n\t%0, %1 + %v0s32i.n\t%1, %0 + %v0s32i.n\t%1, %0 + mov\t%0, %1 +@@ -833,12 +834,14 @@ + const16\t%0, %t1\;const16\t%0, %b1 + %v1l32r\t%0, %1 + %v1l32i\t%0, %1 ++ %v1l32i\t%0, %1 + %v0s32i\t%1, %0 + rsr\t%0, ACCLO + wsr\t%1, ACCLO" +- [(set_attr "type" "move,move,move,load,store,store,move,move,move,move,move,load,load,store,rsr,wsr") ++ [(set_attr "type" "move,move,move,load,load,store,store,move,move,move,move,move,load,load,load,store,rsr,wsr") + (set_attr "mode" "SI") +- (set_attr "length" "2,2,2,2,2,2,3,3,3,3,6,3,3,3,3,3")]) ++ (set_attr "length" "2,2,2,2,2,2,2,3,3,3,3,6,3,3,3,3,3,3") ++ (set_attr "abi" "*,*,*,*,call0,*,*,*,call0,windowed,*,*,*,*,call0,*,*,*")]) + + ;; 16-bit Integer moves + +-- +1.8.1.4 + diff --git a/local-patches/gcc/4.8.2/0013-xtensa-fix-trampolines-generation-for-CALL0-ABI.patch b/local-patches/gcc/4.8.2/0013-xtensa-fix-trampolines-generation-for-CALL0-ABI.patch new file mode 100644 index 000000000..bf2aea36a --- /dev/null +++ b/local-patches/gcc/4.8.2/0013-xtensa-fix-trampolines-generation-for-CALL0-ABI.patch @@ -0,0 +1,232 @@ +From 7234dd9d4ee7af955e1edc20709c06e9d8112581 Mon Sep 17 00:00:00 2001 +From: Max Filippov +Date: Mon, 10 Nov 2014 04:55:15 +0300 +Subject: [PATCH 13/16] xtensa: fix trampolines generation for CALL0 ABI + +Signed-off-by: Max Filippov +--- + gcc/config/xtensa/xtensa.c | 164 +++++++++++++++++++++++++++++++-------------- + gcc/config/xtensa/xtensa.h | 6 +- + 2 files changed, 117 insertions(+), 53 deletions(-) + +diff --git a/gcc/config/xtensa/xtensa.c b/gcc/config/xtensa/xtensa.c +index f44d9ef..1b82c75 100644 +--- a/gcc/config/xtensa/xtensa.c ++++ b/gcc/config/xtensa/xtensa.c +@@ -3730,9 +3730,14 @@ xtensa_function_value_regno_p (const unsigned int regno) + static rtx + xtensa_static_chain (const_tree ARG_UNUSED (fndecl), bool incoming_p) + { +- rtx base = incoming_p ? arg_pointer_rtx : stack_pointer_rtx; +- return gen_frame_mem (Pmode, plus_constant (Pmode, base, +- -5 * UNITS_PER_WORD)); ++ if (TARGET_WINDOWED_ABI) ++ { ++ rtx base = incoming_p ? arg_pointer_rtx : stack_pointer_rtx; ++ return gen_frame_mem (Pmode, plus_constant (Pmode, base, ++ -5 * UNITS_PER_WORD)); ++ } ++ else ++ return gen_rtx_REG (Pmode, A8_REG); + } + + +@@ -3750,65 +3755,109 @@ xtensa_asm_trampoline_template (FILE *stream) + bool use_call0 = (TARGET_CONST16 || TARGET_ABSOLUTE_LITERALS); + + fprintf (stream, "\t.begin no-transform\n"); +- fprintf (stream, "\tentry\tsp, %d\n", MIN_FRAME_SIZE); + +- if (use_call0) ++ if (TARGET_WINDOWED_ABI) + { +- /* Save the return address. */ +- fprintf (stream, "\tmov\ta10, a0\n"); ++ fprintf (stream, "\tentry\tsp, %d\n", MIN_FRAME_SIZE); + +- /* Use a CALL0 instruction to skip past the constants and in the +- process get the PC into A0. This allows PC-relative access to +- the constants without relying on L32R. */ +- fprintf (stream, "\tcall0\t.Lskipconsts\n"); +- } +- else +- fprintf (stream, "\tj\t.Lskipconsts\n"); ++ if (use_call0) ++ { ++ /* Save the return address. */ ++ fprintf (stream, "\tmov\ta10, a0\n"); ++ ++ /* Use a CALL0 instruction to skip past the constants and in the ++ process get the PC into A0. This allows PC-relative access to ++ the constants without relying on L32R. */ ++ fprintf (stream, "\tcall0\t.Lskipconsts\n"); ++ } ++ else ++ fprintf (stream, "\tj\t.Lskipconsts\n"); + +- fprintf (stream, "\t.align\t4\n"); +- fprintf (stream, ".Lchainval:%s0\n", integer_asm_op (4, TRUE)); +- fprintf (stream, ".Lfnaddr:%s0\n", integer_asm_op (4, TRUE)); +- fprintf (stream, ".Lskipconsts:\n"); ++ fprintf (stream, "\t.align\t4\n"); ++ fprintf (stream, ".Lchainval:%s0\n", integer_asm_op (4, TRUE)); ++ fprintf (stream, ".Lfnaddr:%s0\n", integer_asm_op (4, TRUE)); ++ fprintf (stream, ".Lskipconsts:\n"); + +- /* Load the static chain and function address from the trampoline. */ +- if (use_call0) +- { +- fprintf (stream, "\taddi\ta0, a0, 3\n"); +- fprintf (stream, "\tl32i\ta9, a0, 0\n"); +- fprintf (stream, "\tl32i\ta8, a0, 4\n"); ++ /* Load the static chain and function address from the trampoline. */ ++ if (use_call0) ++ { ++ fprintf (stream, "\taddi\ta0, a0, 3\n"); ++ fprintf (stream, "\tl32i\ta9, a0, 0\n"); ++ fprintf (stream, "\tl32i\ta8, a0, 4\n"); ++ } ++ else ++ { ++ fprintf (stream, "\tl32r\ta9, .Lchainval\n"); ++ fprintf (stream, "\tl32r\ta8, .Lfnaddr\n"); ++ } ++ ++ /* Store the static chain. */ ++ fprintf (stream, "\ts32i\ta9, sp, %d\n", MIN_FRAME_SIZE - 20); ++ ++ /* Set the proper stack pointer value. */ ++ fprintf (stream, "\tl32i\ta9, a8, 0\n"); ++ fprintf (stream, "\textui\ta9, a9, %d, 12\n", ++ TARGET_BIG_ENDIAN ? 8 : 12); ++ fprintf (stream, "\tslli\ta9, a9, 3\n"); ++ fprintf (stream, "\taddi\ta9, a9, %d\n", -MIN_FRAME_SIZE); ++ fprintf (stream, "\tsub\ta9, sp, a9\n"); ++ fprintf (stream, "\tmovsp\tsp, a9\n"); ++ ++ if (use_call0) ++ /* Restore the return address. */ ++ fprintf (stream, "\tmov\ta0, a10\n"); ++ ++ /* Jump to the instruction following the ENTRY. */ ++ fprintf (stream, "\taddi\ta8, a8, 3\n"); ++ fprintf (stream, "\tjx\ta8\n"); ++ ++ /* Pad size to a multiple of TRAMPOLINE_ALIGNMENT. */ ++ if (use_call0) ++ fprintf (stream, "\t.byte\t0\n"); ++ else ++ fprintf (stream, "\tnop\n"); + } + else + { +- fprintf (stream, "\tl32r\ta9, .Lchainval\n"); +- fprintf (stream, "\tl32r\ta8, .Lfnaddr\n"); +- } +- +- /* Store the static chain. */ +- fprintf (stream, "\ts32i\ta9, sp, %d\n", MIN_FRAME_SIZE - 20); +- +- /* Set the proper stack pointer value. */ +- fprintf (stream, "\tl32i\ta9, a8, 0\n"); +- fprintf (stream, "\textui\ta9, a9, %d, 12\n", +- TARGET_BIG_ENDIAN ? 8 : 12); +- fprintf (stream, "\tslli\ta9, a9, 3\n"); +- fprintf (stream, "\taddi\ta9, a9, %d\n", -MIN_FRAME_SIZE); +- fprintf (stream, "\tsub\ta9, sp, a9\n"); +- fprintf (stream, "\tmovsp\tsp, a9\n"); ++ if (use_call0) ++ { ++ /* Save the return address. */ ++ fprintf (stream, "\tmov\ta10, a0\n"); + +- if (use_call0) +- /* Restore the return address. */ +- fprintf (stream, "\tmov\ta0, a10\n"); ++ /* Use a CALL0 instruction to skip past the constants and in the ++ process get the PC into A0. This allows PC-relative access to ++ the constants without relying on L32R. */ ++ fprintf (stream, "\tcall0\t.Lskipconsts\n"); ++ } ++ else ++ fprintf (stream, "\tj\t.Lskipconsts\n"); + +- /* Jump to the instruction following the ENTRY. */ +- fprintf (stream, "\taddi\ta8, a8, 3\n"); +- fprintf (stream, "\tjx\ta8\n"); ++ fprintf (stream, "\t.align\t4\n"); ++ fprintf (stream, ".Lchainval:%s0\n", integer_asm_op (4, TRUE)); ++ fprintf (stream, ".Lfnaddr:%s0\n", integer_asm_op (4, TRUE)); ++ fprintf (stream, ".Lskipconsts:\n"); + +- /* Pad size to a multiple of TRAMPOLINE_ALIGNMENT. */ +- if (use_call0) +- fprintf (stream, "\t.byte\t0\n"); +- else +- fprintf (stream, "\tnop\n"); ++ /* Load the static chain and function address from the trampoline. */ ++ if (use_call0) ++ { ++ fprintf (stream, "\taddi\ta0, a0, 3\n"); ++ fprintf (stream, "\tl32i\ta8, a0, 0\n"); ++ fprintf (stream, "\tl32i\ta9, a0, 4\n"); ++ fprintf (stream, "\tmov\ta0, a10\n"); ++ } ++ else ++ { ++ fprintf (stream, "\tl32r\ta8, .Lchainval\n"); ++ fprintf (stream, "\tl32r\ta9, .Lfnaddr\n"); ++ } ++ fprintf (stream, "\tjx\ta9\n"); + ++ /* Pad size to a multiple of TRAMPOLINE_ALIGNMENT. */ ++ if (use_call0) ++ fprintf (stream, "\t.byte\t0\n"); ++ else ++ fprintf (stream, "\tnop\n"); ++ } + fprintf (stream, "\t.end no-transform\n"); + } + +@@ -3817,8 +3866,19 @@ xtensa_trampoline_init (rtx m_tramp, tree fndecl, rtx chain) + { + rtx func = XEXP (DECL_RTL (fndecl), 0); + bool use_call0 = (TARGET_CONST16 || TARGET_ABSOLUTE_LITERALS); +- int chain_off = use_call0 ? 12 : 8; +- int func_off = use_call0 ? 16 : 12; ++ int chain_off; ++ int func_off; ++ ++ if (TARGET_WINDOWED_ABI) ++ { ++ chain_off = use_call0 ? 12 : 8; ++ func_off = use_call0 ? 16 : 12; ++ } ++ else ++ { ++ chain_off = use_call0 ? 8 : 4; ++ func_off = use_call0 ? 12 : 8; ++ } + + emit_block_move (m_tramp, assemble_trampoline_template (), + GEN_INT (TRAMPOLINE_SIZE), BLOCK_OP_NORMAL); +diff --git a/gcc/config/xtensa/xtensa.h b/gcc/config/xtensa/xtensa.h +index 23374bc..1670f8c 100644 +--- a/gcc/config/xtensa/xtensa.h ++++ b/gcc/config/xtensa/xtensa.h +@@ -611,7 +611,11 @@ typedef struct xtensa_args + + /* Size in bytes of the trampoline, as an integer. Make sure this is + a multiple of TRAMPOLINE_ALIGNMENT to avoid -Wpadded warnings. */ +-#define TRAMPOLINE_SIZE (TARGET_CONST16 || TARGET_ABSOLUTE_LITERALS ? 60 : 52) ++#define TRAMPOLINE_SIZE (TARGET_WINDOWED_ABI ? \ ++ (TARGET_CONST16 || TARGET_ABSOLUTE_LITERALS ? \ ++ 60 : 52) : \ ++ (TARGET_CONST16 || TARGET_ABSOLUTE_LITERALS ? \ ++ 32 : 24)) + + /* Alignment required for trampolines, in bits. */ + #define TRAMPOLINE_ALIGNMENT 32 +-- +1.8.1.4 + diff --git a/local-patches/gcc/4.8.2/0014-xtensa-drop-special-cases-for-SP-in-machine-definiti.patch b/local-patches/gcc/4.8.2/0014-xtensa-drop-special-cases-for-SP-in-machine-definiti.patch new file mode 100644 index 000000000..d1925a5a9 --- /dev/null +++ b/local-patches/gcc/4.8.2/0014-xtensa-drop-special-cases-for-SP-in-machine-definiti.patch @@ -0,0 +1,159 @@ +From 10543041c49922e358aea2ceebbb13526a7ddfed Mon Sep 17 00:00:00 2001 +From: Max Filippov +Date: Mon, 10 Nov 2014 05:44:03 +0300 +Subject: [PATCH 14/16] xtensa: drop special cases for SP in machine definition + +Instead of adding explicit operations with 'q' constraint for CALL0 ABI +include SP into 'a' and 'D' constraints and make 'q' constraint empty. + +Drop no longer needed abi attribute. + +Signed-off-by: Max Filippov +--- + gcc/config/xtensa/constraints.md | 6 ++--- + gcc/config/xtensa/xtensa.md | 48 ++++++++++++---------------------------- + 2 files changed, 17 insertions(+), 37 deletions(-) + +diff --git a/gcc/config/xtensa/constraints.md b/gcc/config/xtensa/constraints.md +index 53b3ebfa..440c843 100644 +--- a/gcc/config/xtensa/constraints.md ++++ b/gcc/config/xtensa/constraints.md +@@ -19,7 +19,7 @@ + + ;; Register constraints. + +-(define_register_constraint "a" "GR_REGS" ++(define_register_constraint "a" "TARGET_WINDOWED_ABI ? GR_REGS : AR_REGS" + "General-purpose AR registers @code{a0}-@code{a15}, + except @code{a1} (@code{sp}).") + +@@ -36,7 +36,7 @@ + "Floating-point registers @code{f0}-@code{f15}; only available if the + Xtensa Floating-Pointer Coprocessor is configured.") + +-(define_register_constraint "q" "SP_REG" ++(define_register_constraint "q" "TARGET_WINDOWED_ABI ? SP_REG : NO_REGS" + "@internal + The stack pointer (register @code{a1}).") + +@@ -53,7 +53,7 @@ + General-purpose AR registers, but only if the Xtensa 16-Bit Integer + Multiply Option is configured.") + +-(define_register_constraint "D" "TARGET_DENSITY ? GR_REGS: NO_REGS" ++(define_register_constraint "D" "TARGET_DENSITY ? (TARGET_WINDOWED_ABI ? GR_REGS : AR_REGS) : NO_REGS" + "@internal + General-purpose AR registers, but only if the Xtensa Code Density + Option is configured.") +diff --git a/gcc/config/xtensa/xtensa.md b/gcc/config/xtensa/xtensa.md +index 9781080..ba634b4 100644 +--- a/gcc/config/xtensa/xtensa.md ++++ b/gcc/config/xtensa/xtensa.md +@@ -92,15 +92,6 @@ + + (define_attr "length" "" (const_int 1)) + +-(define_attr "abi" "windowed,call0" (const_string "windowed")) +- +-(define_attr "enabled" "" +- (cond [(eq_attr "abi" "windowed") (const_int 1) +- (and (eq_attr "abi" "call0") +- (ne (symbol_ref "TARGET_WINDOWED_ABI") (const_int 1))) +- (const_int 1)] +- (const_int 0)) +- ) + ;; Describe a user's asm statement. + (define_asm_attributes + [(set_attr "type" "multi")]) +@@ -151,25 +142,19 @@ + ;; Addition. + + (define_insn "addsi3" +- [(set (match_operand:SI 0 "register_operand" "=D,D,r,r,r,q,q,q,q,q") +- (plus:SI (match_operand:SI 1 "register_operand" "%d,d,r,r,r,d,d,r,r,r") +- (match_operand:SI 2 "add_operand" "d,O,r,J,N,d,O,r,J,N")))] ++ [(set (match_operand:SI 0 "register_operand" "=D,D,r,r,r") ++ (plus:SI (match_operand:SI 1 "register_operand" "%d,d,r,r,r") ++ (match_operand:SI 2 "add_operand" "d,O,r,J,N")))] + "" + "@ + add.n\t%0, %1, %2 + addi.n\t%0, %1, %d2 + add\t%0, %1, %2 + addi\t%0, %1, %d2 +- addmi\t%0, %1, %x2 +- add.n\t%0, %1, %2 +- addi.n\t%0, %1, %d2 +- add\t%0, %1, %2 +- addi\t%0, %1, %d2 + addmi\t%0, %1, %x2" +- [(set_attr "type" "arith,arith,arith,arith,arith,arith,arith,arith,arith,arith") ++ [(set_attr "type" "arith,arith,arith,arith,arith") + (set_attr "mode" "SI") +- (set_attr "length" "2,2,3,3,3,2,2,3,3,3") +- (set_attr "abi" "*,*,*,*,*,call0,call0,call0,call0,call0")]) ++ (set_attr "length" "2,2,3,3,3")]) + + (define_insn "*addx" + [(set (match_operand:SI 0 "register_operand" "=a") +@@ -196,15 +181,14 @@ + ;; Subtraction. + + (define_insn "subsi3" +- [(set (match_operand:SI 0 "register_operand" "=a,q") +- (minus:SI (match_operand:SI 1 "register_operand" "r,r") +- (match_operand:SI 2 "register_operand" "r,r")))] ++ [(set (match_operand:SI 0 "register_operand" "=a") ++ (minus:SI (match_operand:SI 1 "register_operand" "r") ++ (match_operand:SI 2 "register_operand" "r")))] + "" + "sub\t%0, %1, %2" +- [(set_attr "type" "arith,arith") ++ [(set_attr "type" "arith") + (set_attr "mode" "SI") +- (set_attr "length" "3,3") +- (set_attr "abi" "*,call0")]) ++ (set_attr "length" "3")]) + + (define_insn "*subx" + [(set (match_operand:SI 0 "register_operand" "=a") +@@ -816,32 +800,28 @@ + }) + + (define_insn "movsi_internal" +- [(set (match_operand:SI 0 "nonimmed_operand" "=D,D,D,D,d,R,R,a,q,q,a,W,a,a,q,U,*a,*A") +- (match_operand:SI 1 "move_operand" "M,D,d,R,R,D,d,r,r,r,I,i,T,U,U,r,*A,*r"))] ++ [(set (match_operand:SI 0 "nonimmed_operand" "=D,D,D,D,R,R,a,q,a,W,a,a,U,*a,*A") ++ (match_operand:SI 1 "move_operand" "M,D,d,R,D,d,r,r,I,i,T,U,r,*A,*r"))] + "xtensa_valid_move (SImode, operands)" + "@ + movi.n\t%0, %x1 + mov.n\t%0, %1 + mov.n\t%0, %1 + %v1l32i.n\t%0, %1 +- %v1l32i.n\t%0, %1 + %v0s32i.n\t%1, %0 + %v0s32i.n\t%1, %0 + mov\t%0, %1 +- mov\t%0, %1 + movsp\t%0, %1 + movi\t%0, %x1 + const16\t%0, %t1\;const16\t%0, %b1 + %v1l32r\t%0, %1 + %v1l32i\t%0, %1 +- %v1l32i\t%0, %1 + %v0s32i\t%1, %0 + rsr\t%0, ACCLO + wsr\t%1, ACCLO" +- [(set_attr "type" "move,move,move,load,load,store,store,move,move,move,move,move,load,load,load,store,rsr,wsr") ++ [(set_attr "type" "move,move,move,load,store,store,move,move,move,move,load,load,store,rsr,wsr") + (set_attr "mode" "SI") +- (set_attr "length" "2,2,2,2,2,2,2,3,3,3,3,6,3,3,3,3,3,3") +- (set_attr "abi" "*,*,*,*,call0,*,*,*,call0,windowed,*,*,*,*,call0,*,*,*")]) ++ (set_attr "length" "2,2,2,2,2,2,3,3,3,6,3,3,3,3,3")]) + + ;; 16-bit Integer moves + +-- +1.8.1.4 + diff --git a/local-patches/gcc/4.8.2/0015-xtensa-fix-addsi3-pattern-for-windowed-ABI.patch b/local-patches/gcc/4.8.2/0015-xtensa-fix-addsi3-pattern-for-windowed-ABI.patch new file mode 100644 index 000000000..fd4066531 --- /dev/null +++ b/local-patches/gcc/4.8.2/0015-xtensa-fix-addsi3-pattern-for-windowed-ABI.patch @@ -0,0 +1,26 @@ +From b26a0f3c3701ad0e6ccc74218e0fdaabcbae414e Mon Sep 17 00:00:00 2001 +From: Max Filippov +Date: Mon, 10 Nov 2014 06:08:22 +0300 +Subject: [PATCH 15/16] xtensa: fix addsi3 pattern for windowed ABI + +Signed-off-by: Max Filippov +--- + gcc/config/xtensa/xtensa.md | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/gcc/config/xtensa/xtensa.md b/gcc/config/xtensa/xtensa.md +index ba634b4..482fd62 100644 +--- a/gcc/config/xtensa/xtensa.md ++++ b/gcc/config/xtensa/xtensa.md +@@ -142,7 +142,7 @@ + ;; Addition. + + (define_insn "addsi3" +- [(set (match_operand:SI 0 "register_operand" "=D,D,r,r,r") ++ [(set (match_operand:SI 0 "register_operand" "=D,D,a,a,a") + (plus:SI (match_operand:SI 1 "register_operand" "%d,d,r,r,r") + (match_operand:SI 2 "add_operand" "d,O,r,J,N")))] + "" +-- +1.8.1.4 + diff --git a/local-patches/gcc/4.8.2/0016-xtensa-don-t-change-entry-pattern-in-machine-descrip.patch b/local-patches/gcc/4.8.2/0016-xtensa-don-t-change-entry-pattern-in-machine-descrip.patch new file mode 100644 index 000000000..ee7b049ee --- /dev/null +++ b/local-patches/gcc/4.8.2/0016-xtensa-don-t-change-entry-pattern-in-machine-descrip.patch @@ -0,0 +1,29 @@ +From 0325ee87614a58948774ece8d9d2718cd9bca367 Mon Sep 17 00:00:00 2001 +From: Max Filippov +Date: Mon, 10 Nov 2014 06:15:26 +0300 +Subject: [PATCH 16/16] xtensa: don't change entry pattern in machine + descripton + +Signed-off-by: Max Filippov +--- + gcc/config/xtensa/xtensa.md | 4 +--- + 1 file changed, 1 insertion(+), 3 deletions(-) + +diff --git a/gcc/config/xtensa/xtensa.md b/gcc/config/xtensa/xtensa.md +index 482fd62..935821b 100644 +--- a/gcc/config/xtensa/xtensa.md ++++ b/gcc/config/xtensa/xtensa.md +@@ -1584,9 +1584,7 @@ + (unspec_volatile:SI [(match_operand:SI 0 "const_int_operand" "i")] + UNSPECV_ENTRY))] + "" +-{ +- return TARGET_WINDOWED_ABI ? "entry\tsp, %0" : "addi\tsp, sp, -%0"; +-} ++ "entry\tsp, %0" + [(set_attr "type" "entry") + (set_attr "mode" "SI") + (set_attr "length" "3")]) +-- +1.8.1.4 +