diff options
Diffstat (limited to 'recipes-microblaze/gcc')
13 files changed, 1001 insertions, 0 deletions
diff --git a/recipes-microblaze/gcc/files/0001-Patch-microblaze-Enable-DWARF-exception-handling-sup.patch b/recipes-microblaze/gcc/files/0001-Patch-microblaze-Enable-DWARF-exception-handling-sup.patch new file mode 100644 index 00000000..d6549cad --- /dev/null +++ b/recipes-microblaze/gcc/files/0001-Patch-microblaze-Enable-DWARF-exception-handling-sup.patch @@ -0,0 +1,158 @@ +From: "Edgar E. Iglesias" <edgar.iglesias@gmail.com> +Subject: [PATCH 1/8] [Patch, microblaze]: Enable DWARF exception handling + support. + +Changelog + +2013-03-18 Edgar E. Iglesias <edgar.iglesias@xilinx.com> + David Holsgrove <david.holsgrove@xilinx.com> + + * common/config/microblaze/microblaze-common.c: Remove + TARGET_EXCEPT_UNWIND_INFO definition. + * config/microblaze/microblaze-protos.h: Add + microblaze_eh_return prototype. + * gcc/config/microblaze/microblaze.c: (microblaze_must_save_register, + microblaze_expand_epilogue, microblaze_return_addr): Handle + calls_eh_return + (microblaze_eh_return): New function. + * gcc/config/microblaze/microblaze.h: Define RETURN_ADDR_OFFSET, + EH_RETURN_DATA_REGNO, MB_EH_STACKADJ_REGNUM, EH_RETURN_STACKADJ_RTX, + ASM_PREFERRED_EH_DATA_FORMAT + * gcc/config/microblaze/microblaze.md: Define eh_return pattern. + +Signed-off-by: David Holsgrove <david.holsgrove@xilinx.com> +Signed-off-by: Edgar E. Iglesias <edgar.iglesias@gmail.com> +Upstream-Status: Pending + +diff --git a/gcc/common/config/microblaze/microblaze-common.c b/gcc/common/config/microblaze/microblaze-common.c +index 07a71fb..6c25a76 100644 +--- a/gcc/common/config/microblaze/microblaze-common.c ++++ b/gcc/common/config/microblaze/microblaze-common.c +@@ -37,7 +37,4 @@ static const struct default_options microblaze_option_optimization_table[] = + #undef TARGET_OPTION_OPTIMIZATION_TABLE + #define TARGET_OPTION_OPTIMIZATION_TABLE microblaze_option_optimization_table + +-#undef TARGET_EXCEPT_UNWIND_INFO +-#define TARGET_EXCEPT_UNWIND_INFO sjlj_except_unwind_info +- + struct gcc_targetm_common targetm_common = TARGETM_COMMON_INITIALIZER; +diff --git a/gcc/config/microblaze/microblaze-protos.h b/gcc/config/microblaze/microblaze-protos.h +index 34be76f..201390b 100644 +--- a/gcc/config/microblaze/microblaze-protos.h ++++ b/gcc/config/microblaze/microblaze-protos.h +@@ -54,6 +54,7 @@ extern bool microblaze_tls_referenced_p (rtx); + extern int symbol_mentioned_p (rtx); + extern int label_mentioned_p (rtx); + extern bool microblaze_cannot_force_const_mem (enum machine_mode, rtx); ++extern void microblaze_eh_return (rtx op0); + #endif /* RTX_CODE */ + + /* Declare functions in microblaze-c.c. */ +diff --git a/gcc/config/microblaze/microblaze.c b/gcc/config/microblaze/microblaze.c +index c121c2b..5f4bc60 100644 +--- a/gcc/config/microblaze/microblaze.c ++++ b/gcc/config/microblaze/microblaze.c +@@ -1896,6 +1896,11 @@ microblaze_must_save_register (int regno) + if (frame_pointer_needed && (regno == HARD_FRAME_POINTER_REGNUM)) + return 1; + ++ if (crtl->calls_eh_return ++ && regno == MB_ABI_SUB_RETURN_ADDR_REGNUM) { ++ return 1; ++ } ++ + if (!crtl->is_leaf) + { + if (regno == MB_ABI_SUB_RETURN_ADDR_REGNUM) +@@ -1923,6 +1928,13 @@ microblaze_must_save_register (int regno) + return 1; + } + ++ if (crtl->calls_eh_return ++ && (regno == EH_RETURN_DATA_REGNO (0) ++ || regno == EH_RETURN_DATA_REGNO (1))) ++ { ++ return 1; ++ } ++ + return 0; + } + +@@ -2939,6 +2951,12 @@ microblaze_expand_epilogue (void) + emit_insn (gen_addsi3 (stack_pointer_rtx, stack_pointer_rtx, fsiz_rtx)); + } + ++ if (crtl->calls_eh_return) ++ emit_insn (gen_addsi3 (stack_pointer_rtx, ++ stack_pointer_rtx, ++ gen_rtx_raw_REG (SImode, ++ MB_EH_STACKADJ_REGNUM))); ++ + emit_jump_insn (gen_return_internal (gen_rtx_REG (Pmode, GP_REG_FIRST + + MB_ABI_SUB_RETURN_ADDR_REGNUM))); + } +@@ -3166,10 +3184,13 @@ microblaze_return_addr (int count, rtx frame ATTRIBUTE_UNUSED) + if (count != 0) + return NULL_RTX; + +- return gen_rtx_PLUS (Pmode, +- get_hard_reg_initial_val (Pmode, +- MB_ABI_SUB_RETURN_ADDR_REGNUM), +- GEN_INT (8)); ++ return get_hard_reg_initial_val (Pmode, ++ MB_ABI_SUB_RETURN_ADDR_REGNUM); ++} ++ ++void microblaze_eh_return (rtx op0) ++{ ++ emit_insn (gen_movsi(gen_rtx_MEM(Pmode, stack_pointer_rtx), op0)); + } + + /* Queue an .ident string in the queue of top-level asm statements. +diff --git a/gcc/config/microblaze/microblaze.h b/gcc/config/microblaze/microblaze.h +index bc4d9a1..074b78e 100644 +--- a/gcc/config/microblaze/microblaze.h ++++ b/gcc/config/microblaze/microblaze.h +@@ -184,6 +184,21 @@ extern enum pipeline_type microblaze_pipe; + #define INCOMING_RETURN_ADDR_RTX \ + gen_rtx_REG (VOIDmode, GP_REG_FIRST + MB_ABI_SUB_RETURN_ADDR_REGNUM) + ++/* Specifies the offset from INCOMING_RETURN_ADDR_RTX and the actual return PC. */ ++#define RETURN_ADDR_OFFSET (8) ++ ++/* Describe how we implement __builtin_eh_return. */ ++#define EH_RETURN_DATA_REGNO(N) (((N) < 2) ? MB_ABI_FIRST_ARG_REGNUM + (N) : INVALID_REGNUM) ++ ++#define MB_EH_STACKADJ_REGNUM MB_ABI_INT_RETURN_VAL2_REGNUM ++#define EH_RETURN_STACKADJ_RTX gen_rtx_REG (Pmode, MB_EH_STACKADJ_REGNUM) ++ ++/* Select a format to encode pointers in exception handling data. CODE ++ is 0 for data, 1 for code labels, 2 for function pointers. GLOBAL is ++ true if the symbol may be affected by dynamic relocations. */ ++#define ASM_PREFERRED_EH_DATA_FORMAT(CODE,GLOBAL) \ ++ ((flag_pic || GLOBAL) ? DW_EH_PE_aligned : DW_EH_PE_absptr) ++ + /* Use DWARF 2 debugging information by default. */ + #define DWARF2_DEBUGGING_INFO + #define PREFERRED_DEBUGGING_TYPE DWARF2_DEBUG +diff --git a/gcc/config/microblaze/microblaze.md b/gcc/config/microblaze/microblaze.md +index 3618cad..4e7fe3b 100644 +--- a/gcc/config/microblaze/microblaze.md ++++ b/gcc/config/microblaze/microblaze.md +@@ -2221,3 +2221,13 @@ + [(set_attr "type" "arith") + (set_attr "mode" "SI") + (set_attr "length" "4")]) ++ ++; This is used in compiling the unwind routines. ++(define_expand "eh_return" ++ [(use (match_operand 0 "general_operand" ""))] ++ "" ++ " ++{ ++ microblaze_eh_return(operands[0]); ++ DONE; ++}") +-- +1.7.5.4 + diff --git a/recipes-microblaze/gcc/files/0002-Patch-microblaze-Add-4-byte-implementation-for-atomi.patch b/recipes-microblaze/gcc/files/0002-Patch-microblaze-Add-4-byte-implementation-for-atomi.patch new file mode 100644 index 00000000..aefa13b0 --- /dev/null +++ b/recipes-microblaze/gcc/files/0002-Patch-microblaze-Add-4-byte-implementation-for-atomi.patch @@ -0,0 +1,157 @@ +From: David Holsgrove <david.holsgrove@xilinx.com> +Subject: [PATCH 2/8] [Patch, microblaze]: Add 4 byte implementation for + atomic builtin + +By providing this initial atomic implementation, gcc is able to generate the other atomic +builtins by using a __sync_compare_and_swap loop + +Add __sync_lock_test_and_set 4 byte atomic builtin + +Changelog + +2013-03-18 David Holsgrove <david.holsgrove@xilinx.com> + + * gcc/config/microblaze/sync.md: New file. + * gcc/config/microblaze/microblaze.md: Add UNSPEC_SYNC_CAS, + UNSPEC_SYNC_XCHG and include sync.md. + * gcc/config/microblaze/microblaze.c: Add print_operand 'y'. + * gcc/config/microblaze/constraints.md: Add memory_contraint + 'Q' which is a single register. + +Signed-off-by: David Holsgrove <david.holsgrove@xilinx.com> +Upstream-Status: Pending + +diff --git a/gcc/config/microblaze/constraints.md b/gcc/config/microblaze/constraints.md +index c6fbc98..c9c1649 100644 +--- a/gcc/config/microblaze/constraints.md ++++ b/gcc/config/microblaze/constraints.md +@@ -70,3 +70,8 @@ + "Double word operand." + (and (match_code "mem") + (match_test "double_memory_operand (op, GET_MODE (op))"))) ++ ++(define_memory_constraint "Q" ++ "Memory operand which is a single register." ++ (and (match_code "mem") ++ (match_test "GET_CODE ( XEXP (op, 0)) == REG"))) +diff --git a/gcc/config/microblaze/microblaze.c b/gcc/config/microblaze/microblaze.c +index 5f4bc60..1562e60 100644 +--- a/gcc/config/microblaze/microblaze.c ++++ b/gcc/config/microblaze/microblaze.c +@@ -2130,6 +2130,7 @@ microblaze_initial_elimination_offset (int from, int to) + 't' print 't' for EQ, 'f' for NE + 'm' Print 1<<operand. + 'i' Print 'i' if MEM operand has immediate value ++ 'y' Print 'y' if MEM operand is single register + 'o' Print operand address+4 + '?' Print 'd' if we use a branch with delay slot instead of normal branch. + 'h' Print high word of const_double (int or float) value as hex +@@ -2300,6 +2301,15 @@ print_operand (FILE * file, rtx op, int letter) + rtx op4 = adjust_address (op, GET_MODE (op), 4); + output_address (XEXP (op4, 0)); + } ++ else if (letter == 'y') ++ { ++ rtx mem_reg = XEXP (op, 0); ++ if (GET_CODE (mem_reg) == REG) ++ { ++ register int regnum = REGNO (mem_reg); ++ fprintf (file, "%s", reg_names[regnum]); ++ } ++ } + else + output_address (XEXP (op, 0)); + +diff --git a/gcc/config/microblaze/microblaze.md b/gcc/config/microblaze/microblaze.md +index 4e7fe3b..55cc730 100644 +--- a/gcc/config/microblaze/microblaze.md ++++ b/gcc/config/microblaze/microblaze.md +@@ -41,6 +41,8 @@ + (UNSPEC_CMP 104) ;; signed compare + (UNSPEC_CMPU 105) ;; unsigned compare + (UNSPEC_TLS 106) ;; jump table ++ (UNSPEC_SYNC_CAS 107) ;; Represent atomic compare swap. ++ (UNSPEC_SYNC_XCHG 108) ;; Represent atomic exchange. + ]) + + +@@ -2231,3 +2233,5 @@ + microblaze_eh_return(operands[0]); + DONE; + }") ++ ++(include "sync.md") +diff --git a/gcc/config/microblaze/sync.md b/gcc/config/microblaze/sync.md +new file mode 100644 +index 0000000..0923825 +--- /dev/null ++++ b/gcc/config/microblaze/sync.md +@@ -0,0 +1,65 @@ ++;; Machine description for Xilinx MicroBlaze synchronization instructions. ++;; Copyright (C) 2011, 2012 ++;; Free Software Foundation, Inc. ++;; ++;; This file is part of GCC. ++;; ++;; GCC is free software; you can redistribute it and/or modify ++;; it under the terms of the GNU General Public License as published by ++;; the Free Software Foundation; either version 3, or (at your option) ++;; any later version. ++;; ++;; GCC is distributed in the hope that it will be useful, ++;; but WITHOUT ANY WARRANTY; without even the implied warranty of ++;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ++;; GNU General Public License for more details. ++;; ++;; You should have received a copy of the GNU General Public License ++;; along with GCC; see the file COPYING3. If not see ++;; <http://www.gnu.org/licenses/>. ++ ++ ++(define_insn "sync_compare_and_swapsi" ++ [(set (match_operand:SI 0 "register_operand" "=&d") ;; retval ++ (match_operand:SI 1 "nonimmediate_operand" "+Q")) ;; mem ++ (set (match_dup 1) ++ (unspec ++ [(match_operand:SI 2 "register_operand" "d") ;; oldval ++ (match_operand:SI 3 "register_operand" "d")] ;; newval ++ UNSPEC_SYNC_CAS)) ++ (clobber (match_scratch:SI 4 "=&d"))] ;; scratch ++ "" ++ { ++ output_asm_insn ("addc \tr0,r0,r0", operands); ++ output_asm_insn ("lwx \t%0,%y1,r0", operands); ++ output_asm_insn ("addic\t%4,r0,0", operands); ++ output_asm_insn ("bnei \t%4,.-8", operands); ++ output_asm_insn ("cmp \t%4,%0,%2", operands); ++ output_asm_insn ("bnei \t%4,.+16", operands); ++ output_asm_insn ("swx \t%3,%y1,r0", operands); ++ output_asm_insn ("addic\t%4,r0,0", operands); ++ output_asm_insn ("bnei \t%4,.-28", operands); ++ return ""; ++ } ++) ++ ++(define_insn "sync_test_and_setsi" ++ [(set (match_operand:SI 0 "register_operand" "=&d") ;; retval ++ (match_operand:SI 1 "nonimmediate_operand" "+Q")) ;; mem ++ (set (match_dup 1) ++ (unspec ++ [(match_operand:SI 2 "register_operand" "d")] ;; value ++ UNSPEC_SYNC_XCHG)) ++ (clobber (match_scratch:SI 3 "=&d"))] ;; scratch ++ "" ++ { ++ output_asm_insn ("addc \tr0,r0,r0", operands); ++ output_asm_insn ("lwx \t%0,%y1,r0", operands); ++ output_asm_insn ("addic\t%3,r0,0", operands); ++ output_asm_insn ("bnei \t%3,.-8", operands); ++ output_asm_insn ("swx \t%2,%y1,r0", operands); ++ output_asm_insn ("addic\t%3,r0,0", operands); ++ output_asm_insn ("bnei \t%3,.-20", operands); ++ return ""; ++ } ++) +-- +1.7.5.4 + diff --git a/recipes-microblaze/gcc/files/0003-Patch-microblaze-Extend-jump-insn-to-accept-bri-to-S.patch b/recipes-microblaze/gcc/files/0003-Patch-microblaze-Extend-jump-insn-to-accept-bri-to-S.patch new file mode 100644 index 00000000..998dfa03 --- /dev/null +++ b/recipes-microblaze/gcc/files/0003-Patch-microblaze-Extend-jump-insn-to-accept-bri-to-S.patch @@ -0,0 +1,35 @@ +From: David Holsgrove <david.holsgrove@xilinx.com> +Subject: [PATCH 3/8] [Patch, microblaze]: Extend jump insn to accept bri to + SYMBOL_REFS + +Current insn checks if operand is a REG - if so, uses br +else it bri to %l0 - using a label_ref print operand + +Check if operand is a SYMBOL_REF, and if so, use %0 + +Changelog + +2013-03-18 David Holsgrove <david.holsgrove@xilinx.com> + + * gcc/config/microblaze/microblaze.md (jump): + Account for jumps to SYMBOL_REFs. + +Signed-off-by: David Holsgrove <david.holsgrove@xilinx.com> +Upstream-Status: Pending + +diff --git a/gcc/config/microblaze/microblaze.md b/gcc/config/microblaze/microblaze.md +index 55cc730..49d8f01 100644 +--- a/gcc/config/microblaze/microblaze.md ++++ b/gcc/config/microblaze/microblaze.md +@@ -1729,6 +1729,8 @@ + { + if (GET_CODE (operands[0]) == REG) + return "br%?\t%0"; ++ else if (GET_CODE (operands[0]) == SYMBOL_REF) ++ return "bri%?\t%0"; + else + return "bri%?\t%l0"; + } +-- +1.7.5.4 + diff --git a/recipes-microblaze/gcc/files/0005-Patch-microblaze-Add-fstack-usage-support.patch b/recipes-microblaze/gcc/files/0005-Patch-microblaze-Add-fstack-usage-support.patch new file mode 100644 index 00000000..ee3cb9db --- /dev/null +++ b/recipes-microblaze/gcc/files/0005-Patch-microblaze-Add-fstack-usage-support.patch @@ -0,0 +1,30 @@ +From: David Holsgrove <david.holsgrove@xilinx.com> +Subject: [PATCH 5/8] [Patch, microblaze]: Add -fstack-usage support + +Changelog + +2013-03-18 David Holsgrove <david.holsgrove@xilinx.com> + + * gcc/config/microblaze/microblaze.c (microblaze_expand_prologue): + Add check for flag_stack_usage to enable -fstack-usage support + +Signed-off-by: David Holsgrove <david.holsgrove@xilinx.com> +Upstream-Status: Pending + +diff --git a/gcc/config/microblaze/microblaze.c b/gcc/config/microblaze/microblaze.c +index 7418e49..4417289 100644 +--- a/gcc/config/microblaze/microblaze.c ++++ b/gcc/config/microblaze/microblaze.c +@@ -2790,6 +2790,9 @@ microblaze_expand_prologue (void) + + fsiz = compute_frame_size (get_frame_size ()); + ++ if (flag_stack_usage) ++ current_function_static_stack_size = fsiz; ++ + /* If this function is a varargs function, store any registers that + would normally hold arguments ($5 - $10) on the stack. */ + if (((TYPE_ARG_TYPES (fntype) != 0 +-- +1.7.5.4 + diff --git a/recipes-microblaze/gcc/files/0006-Patch-microblaze-Remove-SECONDARY_MEMORY_NEEDED.patch b/recipes-microblaze/gcc/files/0006-Patch-microblaze-Remove-SECONDARY_MEMORY_NEEDED.patch new file mode 100644 index 00000000..923756a5 --- /dev/null +++ b/recipes-microblaze/gcc/files/0006-Patch-microblaze-Remove-SECONDARY_MEMORY_NEEDED.patch @@ -0,0 +1,35 @@ +From: "Edgar E. Iglesias" <edgar.iglesias@gmail.com> +Subject: [PATCH 6/8] [Patch, microblaze]: Remove SECONDARY_MEMORY_NEEDED + +MicroBlaze doesn't have restrictions that would force us to +reload regs via memory. Don't define SECONDARY_MEMORY_NEEDED. +Fixes an ICE when compiling OpenSSL for linux. + +Changelog + +2013-03-18 Edgar E. Iglesias <edgar.iglesias@xilinx.com> + + * gcc/config/microblaze/microblaze.h: Remove SECONDARY_MEMORY_NEEDED + definition. + +Signed-off-by: Edgar E. Iglesias <edgar.iglesias@xilinx.com> +Signed-off-by: Peter A. G. Crosthwaite <peter.crosthwaite@xilinx.com> +Upstream-Status: Pending + +diff --git a/gcc/config/microblaze/microblaze.h b/gcc/config/microblaze/microblaze.h +index 074b78e..add69e8 100644 +--- a/gcc/config/microblaze/microblaze.h ++++ b/gcc/config/microblaze/microblaze.h +@@ -422,9 +422,6 @@ extern enum reg_class microblaze_regno_to_class[]; + || GET_MODE (X) == VOIDmode) \ + ? (GR_REGS) : (CLASS)))) + +-#define SECONDARY_MEMORY_NEEDED(CLASS1, CLASS2, MODE) \ +- (GET_MODE_CLASS (MODE) == MODE_INT) +- + /* Stack layout; function entry, exit and calling. */ + + #define STACK_GROWS_DOWNWARD +-- +1.7.5.4 + diff --git a/recipes-microblaze/gcc/files/0007-Patch-microblaze-Add-SIZE_TYPE-and-PTRDIFF_TYPE-to-m.patch b/recipes-microblaze/gcc/files/0007-Patch-microblaze-Add-SIZE_TYPE-and-PTRDIFF_TYPE-to-m.patch new file mode 100644 index 00000000..33aee3a7 --- /dev/null +++ b/recipes-microblaze/gcc/files/0007-Patch-microblaze-Add-SIZE_TYPE-and-PTRDIFF_TYPE-to-m.patch @@ -0,0 +1,39 @@ +From: David Holsgrove <david.holsgrove@xilinx.com> +Subject: [PATCH 7/8] [Patch, microblaze]: Add SIZE_TYPE and PTRDIFF_TYPE to + microblaze.h + +Fixes warnings like; + +warning: format '%zX' expects argument of type 'size_t', +but argument 3 has type 'unsigned int' [-Wformat] + +Changelog + +2013-03-18 David Holsgrove <david.holsgrove@xilinx.com> + + * gcc/config/microblaze/microblaze.h: Define SIZE_TYPE + and PTRDIFF_TYPE. + +Signed-off-by: David Holsgrove <david.holsgrove@xilinx.com> +Upstream-Status: Pending + +diff --git a/gcc/config/microblaze/microblaze.h b/gcc/config/microblaze/microblaze.h +index add69e8..367e986 100644 +--- a/gcc/config/microblaze/microblaze.h ++++ b/gcc/config/microblaze/microblaze.h +@@ -228,6 +228,12 @@ extern enum pipeline_type microblaze_pipe; + #define STRICT_ALIGNMENT 1 + #define PCC_BITFIELD_TYPE_MATTERS 1 + ++#undef SIZE_TYPE ++#define SIZE_TYPE "unsigned int" ++ ++#undef PTRDIFF_TYPE ++#define PTRDIFF_TYPE "int" ++ + #define CONSTANT_ALIGNMENT(EXP, ALIGN) \ + ((TREE_CODE (EXP) == STRING_CST || TREE_CODE (EXP) == CONSTRUCTOR) \ + && (ALIGN) < BITS_PER_WORD \ +-- +1.7.5.4 + diff --git a/recipes-microblaze/gcc/files/0008-Patch-microblaze-Add-branch_compare-instruction.patch b/recipes-microblaze/gcc/files/0008-Patch-microblaze-Add-branch_compare-instruction.patch new file mode 100644 index 00000000..4da74f3f --- /dev/null +++ b/recipes-microblaze/gcc/files/0008-Patch-microblaze-Add-branch_compare-instruction.patch @@ -0,0 +1,224 @@ +From: David Holsgrove <david.holsgrove@xilinx.com> +Subject: [PATCH 8/8] [Patch, microblaze]: Add branch_compare instruction + +To facilitate optimization pass understanding of the conditional +branch for microblaze, remove the UNSPEC'd signed_compare / +unsigned_compare instructions, and replace with a complete +branch_compare which will output_asm_insn the correct cmp/cmpu +depending on comparison code and signed / unsigned. + +We then return the correct branch instruction. + +cbranchsi now calls an expanded microblaze_expand_conditional_branch +function which will carry out compare against zero, compare EQ/NE, +and all other compares appropriately. + +-funroll-loops optimization pass can now proceed + +Changelog + +2013-03-19 David Holsgrove <david.holsgrove@xilinx.com> + + * gcc/config/microblaze/predicates.md: Add cmp_op predicate. + * gcc/config/microblaze/microblaze.md: Add branch_compare + instruction which uses cmp_op predicate and emits cmp insn + before branch. + * gcc/config/microblaze/microblaze.c + (microblaze_emit_compare): Rename to + microblaze_expand_conditional_branch and consolidate logic. + (microblaze_expand_conditional_branch): emit branch_compare + insn instead of handling cmp op separate from branch insn. + +Signed-off-by: David Holsgrove <david.holsgrove@xilinx.com> +Upstream-Status: Pending + +diff --git a/gcc/config/microblaze/microblaze.c b/gcc/config/microblaze/microblaze.c +index 4417289..84b58bf 100644 +--- a/gcc/config/microblaze/microblaze.c ++++ b/gcc/config/microblaze/microblaze.c +@@ -3336,65 +3336,45 @@ microblaze_trampoline_init (rtx m_tramp, tree fndecl, rtx chain_value) + emit_move_insn (mem, fnaddr); + } + +-/* Emit instruction to perform compare. +- cmp is (compare_op op0 op1). */ +-static rtx +-microblaze_emit_compare (enum machine_mode mode, rtx cmp, enum rtx_code *cmp_code) ++/* Generate conditional branch -- first, generate test condition, ++ second, generate correct branch instruction. */ ++ ++void ++microblaze_expand_conditional_branch (enum machine_mode mode, rtx operands[]) + { +- rtx cmp_op0 = XEXP (cmp, 0); +- rtx cmp_op1 = XEXP (cmp, 1); ++ enum rtx_code code = GET_CODE (operands[0]); ++ rtx cmp_op0 = operands[1]; ++ rtx cmp_op1 = operands[2]; ++ rtx label1 = operands[3]; + rtx comp_reg = gen_reg_rtx (SImode); +- enum rtx_code code = *cmp_code; +- ++ rtx condition; ++ + gcc_assert ((GET_CODE (cmp_op0) == REG) || (GET_CODE (cmp_op0) == SUBREG)); + + /* If comparing against zero, just test source reg. */ +- if (cmp_op1 == const0_rtx) +- return cmp_op0; ++ if (cmp_op1 == const0_rtx) ++ { ++ comp_reg = cmp_op0; ++ condition = gen_rtx_fmt_ee (signed_condition (code), SImode, comp_reg, const0_rtx); ++ emit_jump_insn (gen_condjump (condition, label1)); ++ } + +- if (code == EQ || code == NE) ++ else if (code == EQ || code == NE) + { + /* Use xor for equal/not-equal comparison. */ + emit_insn (gen_xorsi3 (comp_reg, cmp_op0, cmp_op1)); ++ condition = gen_rtx_fmt_ee (signed_condition (code), SImode, comp_reg, const0_rtx); ++ emit_jump_insn (gen_condjump (condition, label1)); + } +- else if (code == GT || code == GTU || code == LE || code == LEU) +- { +- /* MicroBlaze compare is not symmetrical. */ +- /* Swap argument order. */ +- cmp_op1 = force_reg (mode, cmp_op1); +- if (code == GT || code == LE) +- emit_insn (gen_signed_compare (comp_reg, cmp_op0, cmp_op1)); +- else +- emit_insn (gen_unsigned_compare (comp_reg, cmp_op0, cmp_op1)); +- /* Translate test condition. */ +- *cmp_code = swap_condition (code); +- } +- else /* if (code == GE || code == GEU || code == LT || code == LTU) */ ++ else + { ++ /* Generate compare and branch in single instruction. */ + cmp_op1 = force_reg (mode, cmp_op1); +- if (code == GE || code == LT) +- emit_insn (gen_signed_compare (comp_reg, cmp_op1, cmp_op0)); +- else +- emit_insn (gen_unsigned_compare (comp_reg, cmp_op1, cmp_op0)); ++ condition = gen_rtx_fmt_ee (code, mode, cmp_op0, cmp_op1); ++ emit_jump_insn (gen_branch_compare(condition, cmp_op0, cmp_op1, label1)); + } +- +- return comp_reg; + } + +-/* Generate conditional branch -- first, generate test condition, +- second, generate correct branch instruction. */ +- +-void +-microblaze_expand_conditional_branch (enum machine_mode mode, rtx operands[]) +-{ +- enum rtx_code code = GET_CODE (operands[0]); +- rtx comp; +- rtx condition; +- +- comp = microblaze_emit_compare (mode, operands[0], &code); +- condition = gen_rtx_fmt_ee (signed_condition (code), SImode, comp, const0_rtx); +- emit_jump_insn (gen_condjump (condition, operands[3])); +-} + + void + microblaze_expand_conditional_branch_sf (rtx operands[]) +diff --git a/gcc/config/microblaze/microblaze.md b/gcc/config/microblaze/microblaze.md +index 49d8f01..9c1e1a3 100644 +--- a/gcc/config/microblaze/microblaze.md ++++ b/gcc/config/microblaze/microblaze.md +@@ -1624,28 +1624,6 @@ + (set_attr "length" "4")] + ) + +-(define_insn "signed_compare" +- [(set (match_operand:SI 0 "register_operand" "=d") +- (unspec +- [(match_operand:SI 1 "register_operand" "d") +- (match_operand:SI 2 "register_operand" "d")] UNSPEC_CMP))] +- "" +- "cmp\t%0,%1,%2" +- [(set_attr "type" "arith") +- (set_attr "mode" "SI") +- (set_attr "length" "4")]) +- +-(define_insn "unsigned_compare" +- [(set (match_operand:SI 0 "register_operand" "=d") +- (unspec +- [(match_operand:SI 1 "register_operand" "d") +- (match_operand:SI 2 "register_operand" "d")] UNSPEC_CMPU))] +- "" +- "cmpu\t%0,%1,%2" +- [(set_attr "type" "arith") +- (set_attr "mode" "SI") +- (set_attr "length" "4")]) +- + ;;---------------------------------------------------------------- + ;; Setting a register from an floating point comparison. + ;;---------------------------------------------------------------- +@@ -1719,6 +1697,47 @@ + (set_attr "length" "4")] + ) + ++(define_insn "branch_compare" ++ [(set (pc) ++ (if_then_else (match_operator:SI 0 "cmp_op" ++ [(match_operand:SI 1 "register_operand" "d") ++ (match_operand:SI 2 "register_operand" "d") ++ ]) ++ (label_ref (match_operand 3)) ++ (pc))) ++ (clobber(reg:SI R_TMP))] ++ "" ++ { ++ operands[4] = gen_rtx_REG (SImode, MB_ABI_ASM_TEMP_REGNUM); ++ enum rtx_code code = GET_CODE (operands[0]); ++ ++ if (code == GT || code == LE) ++ { ++ output_asm_insn ("cmp\tr18,%z1,%z2", operands); ++ code = swap_condition (code); ++ } ++ else if (code == GTU || code == LEU) ++ { ++ output_asm_insn ("cmpu\tr18,%z1,%z2", operands); ++ code = swap_condition (code); ++ } ++ else if (code == GE || code == LT) ++ { ++ output_asm_insn ("cmp\tr18,%z2,%z1", operands); ++ } ++ else if (code == GEU || code == LTU) ++ { ++ output_asm_insn ("cmpu\tr18,%z2,%z1", operands); ++ } ++ ++ operands[0] = gen_rtx_fmt_ee (signed_condition (code), SImode, operands[4], const0_rtx); ++ return "b%C0i%?\tr18,%3"; ++ } ++ [(set_attr "type" "branch") ++ (set_attr "mode" "none") ++ (set_attr "length" "12")] ++) ++ + ;;---------------------------------------------------------------- + ;; Unconditional branches + ;;---------------------------------------------------------------- +diff --git a/gcc/config/microblaze/predicates.md b/gcc/config/microblaze/predicates.md +index 5fd1bd4..2c23291 100644 +--- a/gcc/config/microblaze/predicates.md ++++ b/gcc/config/microblaze/predicates.md +@@ -119,3 +119,7 @@ + ;; Test for valid PIC call operand + (define_predicate "call_insn_plt_operand" + (match_test "PLT_ADDR_P (op)")) ++ ++;; Return if the code of this rtx pattern is a comparison. ++(define_predicate "cmp_op" ++ (match_code "gt,ge,gtu,geu,lt,le,ltu,leu")) +-- +1.7.5.4 + diff --git a/recipes-microblaze/gcc/files/0462b5f-2014-02-23-David-Holsgrove-david.holsgrove.patch b/recipes-microblaze/gcc/files/0462b5f-2014-02-23-David-Holsgrove-david.holsgrove.patch new file mode 100644 index 00000000..efd127de --- /dev/null +++ b/recipes-microblaze/gcc/files/0462b5f-2014-02-23-David-Holsgrove-david.holsgrove.patch @@ -0,0 +1,108 @@ +From 0462b5fb1e91183c16e204e1a6cf436ef0d8d0f8 Mon Sep 17 00:00:00 2001 +From: eager <eager@138bc75d-0d04-0410-961f-82ee72b054a4> +Date: Sun, 23 Feb 2014 18:44:27 +0000 +Subject: [PATCH] 2014-02-23 David Holsgrove <david.holsgrove@xilinx.com> + + * /config/microblaze/microblaze.c: Add microblaze_asm_output_mi_thunk + and define TARGET_ASM_OUTPUT_MI_THUNK and + TARGET_ASM_CAN_OUTPUT_MI_THUNK. + +Upstream-Status: Backport +--- + gcc/config/microblaze/microblaze.c | 73 ++++++++++++++++++++++++++++++++++++++ + 2 files changed, 79 insertions(+) + +diff --git a/gcc/config/microblaze/microblaze.c b/gcc/config/microblaze/microblaze.c +index 985d26a..ba8109b 100644 +--- a/gcc/config/microblaze/microblaze.c ++++ b/gcc/config/microblaze/microblaze.c +@@ -3087,6 +3087,73 @@ expand_pic_symbol_ref (enum machine_mode mode ATTRIBUTE_UNUSED, rtx op) + return result; + } + ++static void ++microblaze_asm_output_mi_thunk (FILE *file, tree thunk_fndecl ATTRIBUTE_UNUSED, ++ HOST_WIDE_INT delta, HOST_WIDE_INT vcall_offset, ++ tree function) ++{ ++ rtx this_rtx, insn, funexp; ++ ++ reload_completed = 1; ++ epilogue_completed = 1; ++ ++ /* Mark the end of the (empty) prologue. */ ++ emit_note (NOTE_INSN_PROLOGUE_END); ++ ++ /* Find the "this" pointer. If the function returns a structure, ++ the structure return pointer is in MB_ABI_FIRST_ARG_REGNUM. */ ++ if (aggregate_value_p (TREE_TYPE (TREE_TYPE (function)), function)) ++ this_rtx = gen_rtx_REG (Pmode, (MB_ABI_FIRST_ARG_REGNUM + 1)); ++ else ++ this_rtx = gen_rtx_REG (Pmode, MB_ABI_FIRST_ARG_REGNUM); ++ ++ /* Apply the constant offset, if required. */ ++ if (delta) ++ emit_insn (gen_addsi3 (this_rtx, this_rtx, GEN_INT (delta))); ++ ++ /* Apply the offset from the vtable, if required. */ ++ if (vcall_offset) ++ { ++ rtx vcall_offset_rtx = GEN_INT (vcall_offset); ++ rtx temp1 = gen_rtx_REG (Pmode, MB_ABI_TEMP1_REGNUM); ++ ++ emit_move_insn (temp1, gen_rtx_MEM (Pmode, this_rtx)); ++ ++ rtx loc = gen_rtx_PLUS (Pmode, temp1, vcall_offset_rtx); ++ emit_move_insn (temp1, gen_rtx_MEM (Pmode, loc)); ++ ++ emit_insn (gen_addsi3 (this_rtx, this_rtx, temp1)); ++ } ++ ++ /* Generate a tail call to the target function. */ ++ if (!TREE_USED (function)) ++ { ++ assemble_external (function); ++ TREE_USED (function) = 1; ++ } ++ ++ funexp = XEXP (DECL_RTL (function), 0); ++ rtx temp2 = gen_rtx_REG (Pmode, MB_ABI_TEMP2_REGNUM); ++ ++ if (flag_pic) ++ emit_move_insn (temp2, expand_pic_symbol_ref (Pmode, funexp)); ++ else ++ emit_move_insn (temp2, funexp); ++ ++ emit_insn (gen_indirect_jump (temp2)); ++ ++ /* Run just enough of rest_of_compilation. This sequence was ++ "borrowed" from rs6000.c. */ ++ insn = get_insns (); ++ shorten_branches (insn); ++ final_start_function (insn, file, 1); ++ final (insn, file, 1); ++ final_end_function (); ++ ++ reload_completed = 0; ++ epilogue_completed = 0; ++} ++ + bool + microblaze_expand_move (enum machine_mode mode, rtx operands[]) + { +@@ -3504,6 +3571,12 @@ microblaze_legitimate_constant_p (enum machine_mode mode ATTRIBUTE_UNUSED, rtx x + #undef TARGET_SECONDARY_RELOAD + #define TARGET_SECONDARY_RELOAD microblaze_secondary_reload + ++#undef TARGET_ASM_OUTPUT_MI_THUNK ++#define TARGET_ASM_OUTPUT_MI_THUNK microblaze_asm_output_mi_thunk ++ ++#undef TARGET_ASM_CAN_OUTPUT_MI_THUNK ++#define TARGET_ASM_CAN_OUTPUT_MI_THUNK hook_bool_const_tree_hwi_hwi_const_tree_true ++ + #undef TARGET_SCHED_ADJUST_COST + #define TARGET_SCHED_ADJUST_COST microblaze_adjust_cost + +-- +1.9.0 + diff --git a/recipes-microblaze/gcc/files/Patch-microblaze-Fix-bswaphi2-implementation.patch b/recipes-microblaze/gcc/files/Patch-microblaze-Fix-bswaphi2-implementation.patch new file mode 100644 index 00000000..b39dc4db --- /dev/null +++ b/recipes-microblaze/gcc/files/Patch-microblaze-Fix-bswaphi2-implementation.patch @@ -0,0 +1,44 @@ +From: David Holsgrove <david.holsgrove@xilinx.com> +Subject: [PATCH] [Patch, microblaze]: Fix bswaphi2 implementation + +MicroBlaze insn swaph swaps the contents of register rA +as two halfwords placing result in rD; + +(rD)[0:15] <- (rA)[16:31] +(rD)[16:31] <- (rA)[0:15] + +gcc bswaphi2 is intended to reverse the order of the bytes +in the half integer in rA + +(rD)[8:15] <- (rA)[0:7] +(rD)[7:0] <- (rA)[8:15] +(rD)[24:31] <- (rA)[16:23] +(rD)[16:23] <- (rA)[24:31] + +Correct microblaze bswaphi2 insn pattern to be a +swapb followed by swaph + +Reported-by: Nathan Rossi <nathan.rossi@xilinx.com> +Signed-off-by: David Holsgrove <david.holsgrove@xilinx.com> +Upstream-Status: Pending +--- + gcc/config/microblaze/microblaze.md | 3 ++- + 1 files changed, 2 insertions(+), 1 deletions(-) + +diff --git a/gcc/config/microblaze/microblaze.md b/gcc/config/microblaze/microblaze.md +index ae4ade7..c7485fc 100644 +--- a/gcc/config/microblaze/microblaze.md ++++ b/gcc/config/microblaze/microblaze.md +@@ -367,7 +367,8 @@ + [(set (match_operand:HI 0 "register_operand" "=r") + (bswap:HI (match_operand:HI 1 "register_operand" "r")))] + "TARGET_REORDER" +- "swaph %0, %1" ++ "swapb %0, %1 ++ swaph %0, %0" + ) + + ;;---------------------------------------------------------------- +-- +1.7.1 + diff --git a/recipes-microblaze/gcc/files/Patch-microblaze-cstoresf4-add-mode-and-ordered_comp.patch b/recipes-microblaze/gcc/files/Patch-microblaze-cstoresf4-add-mode-and-ordered_comp.patch new file mode 100644 index 00000000..934e7fa9 --- /dev/null +++ b/recipes-microblaze/gcc/files/Patch-microblaze-cstoresf4-add-mode-and-ordered_comp.patch @@ -0,0 +1,44 @@ +From: David Holsgrove <david.holsgrove@xilinx.com> +Subject: [PATCH] [Patch, microblaze]: cstoresf4, add mode and + ordered_comparison_operator + +Add SImode to comparison operator, prevents ICE during combine +rtl pass with error message; + +internal compiler error: in simplify_subreg, at simplify-rtx.c:5725 + +Use ordered_comparison_operator predicate to limit operators to +those fcmp can handle, and letting compiler reorder insns to +accomodate unordered as necessary + +Signed-off-by: David Holsgrove <david.holsgrove@xilinx.com> +Upstream-Status: Pending +--- + gcc/config/microblaze/microblaze.md | 4 ++-- + 1 file changed, 2 insertions(+), 2 deletions(-) + +diff --git a/gcc/config/microblaze/microblaze.md b/gcc/config/microblaze/microblaze.md +index 786dabb..e9b032b 100644 +--- a/gcc/config/microblaze/microblaze.md ++++ b/gcc/config/microblaze/microblaze.md +@@ -1650,7 +1650,7 @@ + ;;---------------------------------------------------------------- + (define_insn "cstoresf4" + [(set (match_operand:SI 0 "register_operand" "=r") +- (match_operator 1 "comparison_operator" ++ (match_operator:SI 1 "ordered_comparison_operator" + [(match_operand:SF 2 "register_operand" "r") + (match_operand:SF 3 "register_operand" "r")]))] + "TARGET_HARD_FLOAT" +@@ -1679,7 +1679,7 @@ + + (define_expand "cbranchsf4" + [(set (pc) +- (if_then_else (match_operator 0 "comparison_operator" ++ (if_then_else (match_operator 0 "ordered_comparison_operator" + [(match_operand:SF 1 "register_operand") + (match_operand:SF 2 "register_operand")]) + (label_ref (match_operand 3 "")) +-- +1.7.9.5 + diff --git a/recipes-microblaze/gcc/files/gcc-Cherry-pick-mainline-patch-to-resolve-MB-k.patch b/recipes-microblaze/gcc/files/gcc-Cherry-pick-mainline-patch-to-resolve-MB-k.patch new file mode 100644 index 00000000..1cdc4029 --- /dev/null +++ b/recipes-microblaze/gcc/files/gcc-Cherry-pick-mainline-patch-to-resolve-MB-k.patch @@ -0,0 +1,110 @@ +Subject: Cherry-pick mainline patch to resolve MB kernel panic + +Cherry-pick backend optimization patch from gcc HEAD which 'resolves' a kernel +panic for microblaze when compiled with -Os + +Upstream HEAD (soon to be gcc 4.9) does not exhibt this error any longer, +and this patch when applied as a workaround on the 4.8 branch also hides the +kernel panic resulting from incorrect branch-delay slot filling. + + * tree-ssa-threadedge.c (thread_around_empty_block): Remove + checks for the number of predecessors and successors allowed. + * tree-ssa-threadupdate.c (mark_threaded_blocks): Ignore requests + which require copying a joiner block if there is a request which + is a subpath that requires no joiner block copying. + +Signed-off-by: David Holsgrove <david.holsgrove@xilinx.com> +Upstream-Status: Backport +--- + gcc/tree-ssa-threadedge.c | 8 ------- + gcc/tree-ssa-threadupdate.c | 49 ++++++++++++++++++++++++++++++++++++++----- + 2 files changed, 44 insertions(+), 13 deletions(-) + +diff --git a/gcc/tree-ssa-threadedge.c b/gcc/tree-ssa-threadedge.c +index b31e961..ab58ae8 100644 +--- a/gcc/tree-ssa-threadedge.c ++++ b/gcc/tree-ssa-threadedge.c +@@ -761,14 +761,6 @@ thread_around_empty_block (edge taken_edge, + gimple stmt; + tree cond; + +- /* This block must have a single predecessor (E->dest). */ +- if (!single_pred_p (bb)) +- return NULL; +- +- /* This block must have more than one successor. */ +- if (single_succ_p (bb)) +- return NULL; +- + /* This block can have no PHI nodes. This is overly conservative. */ + if (!gsi_end_p (gsi_start_phis (bb))) + return NULL; +diff --git a/gcc/tree-ssa-threadupdate.c b/gcc/tree-ssa-threadupdate.c +index 0e4cbc9..cf8df8e 100644 +--- a/gcc/tree-ssa-threadupdate.c ++++ b/gcc/tree-ssa-threadupdate.c +@@ -1146,17 +1146,56 @@ mark_threaded_blocks (bitmap threaded_blocks) + edge e; + edge_iterator ei; + ++ /* It is possible to have jump threads in which one is a subpath ++ of the other. ie, (A, B), (B, C), (C, D) where B is a joiner ++ block and (B, C), (C, D) where no joiner block exists. ++ ++ When this occurs ignore the jump thread request with the joiner ++ block. It's totally subsumed by the simpler jump thread request. ++ ++ This results in less block copying, simpler CFGs. More improtantly, ++ when we duplicate the joiner block, B, in this case we will create ++ a new threading opportunity that we wouldn't be able to optimize ++ until the next jump threading iteration. ++ ++ So first convert the jump thread requests which do not require a ++ joiner block. */ + for (i = 0; i < threaded_edges.length (); i += 3) + { + edge e = threaded_edges[i]; +- edge *x = XNEWVEC (edge, 2); + +- e->aux = x; +- THREAD_TARGET (e) = threaded_edges[i + 1]; +- THREAD_TARGET2 (e) = threaded_edges[i + 2]; +- bitmap_set_bit (tmp, e->dest->index); ++ if (threaded_edges[i + 2] == NULL) ++ { ++ edge *x = XNEWVEC (edge, 2); ++ ++ e->aux = x; ++ THREAD_TARGET (e) = threaded_edges[i + 1]; ++ THREAD_TARGET2 (e) = NULL; ++ bitmap_set_bit (tmp, e->dest->index); ++ } + } + ++ ++ /* Now iterate again, converting cases where we threaded through ++ a joiner block, but ignoring those where we have already ++ threaded through the joiner block. */ ++ for (i = 0; i < threaded_edges.length (); i += 3) ++ { ++ edge e = threaded_edges[i]; ++ ++ if (threaded_edges[i + 2] != NULL ++ && threaded_edges[i + 1]->aux == NULL) ++ { ++ edge *x = XNEWVEC (edge, 2); ++ ++ e->aux = x; ++ THREAD_TARGET (e) = threaded_edges[i + 1]; ++ THREAD_TARGET2 (e) = threaded_edges[i + 2]; ++ bitmap_set_bit (tmp, e->dest->index); ++ } ++ } ++ ++ + /* If optimizing for size, only thread through block if we don't have + to duplicate it or it's an otherwise empty redirection block. */ + if (optimize_function_for_size_p (cfun)) +-- +1.7.9.5 + diff --git a/recipes-microblaze/gcc/gcc-microblaze-4.8.inc b/recipes-microblaze/gcc/gcc-microblaze-4.8.inc new file mode 100644 index 00000000..f0578dbd --- /dev/null +++ b/recipes-microblaze/gcc/gcc-microblaze-4.8.inc @@ -0,0 +1,16 @@ + +# Add MicroBlaze Patches +FILESEXTRAPATHS_append := "${THISDIR}/files:" +SRC_URI_append += " \ + file://0001-Patch-microblaze-Enable-DWARF-exception-handling-sup.patch \ + file://0002-Patch-microblaze-Add-4-byte-implementation-for-atomi.patch \ + file://0003-Patch-microblaze-Extend-jump-insn-to-accept-bri-to-S.patch \ + file://0462b5f-2014-02-23-David-Holsgrove-david.holsgrove.patch \ + file://0005-Patch-microblaze-Add-fstack-usage-support.patch \ + file://0006-Patch-microblaze-Remove-SECONDARY_MEMORY_NEEDED.patch \ + file://0007-Patch-microblaze-Add-SIZE_TYPE-and-PTRDIFF_TYPE-to-m.patch \ + file://0008-Patch-microblaze-Add-branch_compare-instruction.patch \ + file://Patch-microblaze-Fix-bswaphi2-implementation.patch \ + file://Patch-microblaze-cstoresf4-add-mode-and-ordered_comp.patch \ + file://gcc-Cherry-pick-mainline-patch-to-resolve-MB-k.patch \ + " diff --git a/recipes-microblaze/gcc/gcc-source_4.8.bbappend b/recipes-microblaze/gcc/gcc-source_4.8.bbappend new file mode 100644 index 00000000..e28b4dd0 --- /dev/null +++ b/recipes-microblaze/gcc/gcc-source_4.8.bbappend @@ -0,0 +1 @@ +require gcc-microblaze-4.8.inc |