diff options
Diffstat (limited to 'patches/gcc-4.2.3/generic/gentoo/91_all_mips-ip28_cache_barriers-v4.patch')
-rw-r--r-- | patches/gcc-4.2.3/generic/gentoo/91_all_mips-ip28_cache_barriers-v4.patch | 352 |
1 files changed, 0 insertions, 352 deletions
diff --git a/patches/gcc-4.2.3/generic/gentoo/91_all_mips-ip28_cache_barriers-v4.patch b/patches/gcc-4.2.3/generic/gentoo/91_all_mips-ip28_cache_barriers-v4.patch deleted file mode 100644 index 48d52f6..0000000 --- a/patches/gcc-4.2.3/generic/gentoo/91_all_mips-ip28_cache_barriers-v4.patch +++ /dev/null @@ -1,352 +0,0 @@ ---- - gcc/config/mips/mips.c | 7 - gcc/config/mips/mips.opt | 10 + - gcc/config/mips/r10k-cacheb.c | 298 ++++++++++++++++++++++++++++++++++++++++++ - 3 files changed, 315 insertions(+) - -Index: gcc-4.2.3/gcc/config/mips/mips.c -=================================================================== ---- gcc-4.2.3.orig/gcc/config/mips/mips.c -+++ gcc-4.2.3/gcc/config/mips/mips.c -@@ -255,6 +255,9 @@ static const char *const mips_fp_conditi - MIPS_FP_CONDITIONS (STRINGIFY) - }; - -+/* R10K Cache Barrier Functions */ -+#include "r10k-cacheb.c" -+ - /* A function to save or store a register. The first argument is the - register and the second is the stack slot. */ - typedef void (*mips_save_restore_fn) (rtx, rtx); -@@ -8908,6 +8911,10 @@ vr4130_avoid_branch_rt_conflict (rtx ins - XEXP (cond, 1) = tmp; - } - } -+ if (TARGET_R10K_SPECEX) -+ { -+ r10k_insert_cache_barriers (); -+ } - } - - /* Implement -mvr4130-align. Go through each basic block and simulate the -Index: gcc-4.2.3/gcc/config/mips/mips.opt -=================================================================== ---- gcc-4.2.3.orig/gcc/config/mips/mips.opt -+++ gcc-4.2.3/gcc/config/mips/mips.opt -@@ -219,3 +219,13 @@ Perform VR4130-specific alignment optimi - mxgot - Target Report Var(TARGET_XGOT) - Lift restrictions on GOT size -+ -+mr10k-cache-barrier= -+Target Report Joined UInteger Var(TARGET_R10K_SPECEX) -+-mr10k-cache-barrier[=1|2] Generate cache barriers for SGI Indigo2/O2 R10k -+ -+mr10k-cache-barrier -+Target Undocumented Var(TARGET_R10K_SPECEX) VarExists -+ -+mip28-cache-barrier -+Target Undocumented Var(TARGET_R10K_SPECEX) VarExists -Index: gcc-4.2.3/gcc/config/mips/r10k-cacheb.c -=================================================================== ---- /dev/null -+++ gcc-4.2.3/gcc/config/mips/r10k-cacheb.c -@@ -0,0 +1,298 @@ -+/* Subroutines used for MIPS code generation: generate cache-barriers -+ for SiliconGraphics IP28 and IP32/R10000 kernel-code. -+ Copyright (C) 2005,2006 peter fuerst, pf@net.alphadv.de. -+ -+This file is intended to become part of GCC. -+ -+This file 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 2, or (at your -+option) any later version. -+ -+This file 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 COPYING. If not, write to the -+Free Software Foundation, 51 Franklin Street, Fifth Floor, Boston, -+MA 02110-1301 USA. */ -+ -+ -+#define ASM_R10K_CACHE_BARRIER "cache 0x14,0($sp)" -+ -+static int is_stack_pointer (rtx *x, void *data); -+static int check_p_mem_expr (rtx *memx, void *data); -+static int check_p_pattern_for_store (rtx *body, void *data); -+static int strmatch (const char *txt, const char *match); -+static int check_insn_for_store (int state, rtx insn); -+static int bb_insert_store_cache_barrier (rtx head, rtx nxtb); -+static int scan_1_bb_for_store (rtx head, rtx end); -+static int r10k_insert_cache_barriers (void); -+ -+ -+/* Check, whether an instruction is a possibly harmful store instruction, -+ i.e. a store which might cause damage, if speculatively executed. */ -+ -+/* Return truth value whether the expression `*memx' instantiates -+ (mem:M (not (stackpointer_address or constant))). */ -+ -+static int -+is_stack_pointer (rtx *x, void *data) -+{ -+ return (*x == stack_pointer_rtx); -+} -+ -+static int -+check_p_mem_expr (rtx *memx, void *data) -+{ -+ if (!MEM_P (*memx) || for_each_rtx (memx, is_stack_pointer, 0)) -+ return 0; -+ -+ /* Stores/Loads to/from constant addresses can be considered -+ harmless, since: -+ 1) the address is always valid, even when taken speculatively. -+ 2a) the location is (hopefully) never used as a dma-target, thus -+ there is no danger of cache-inconsistency. -+ 2b) uncached loads/stores are guaranteed to be non-speculative. */ -+ if ( CONSTANT_P(XEXP (*memx, 0)) ) -+ return 0; -+ -+ return 1; -+} -+ -+/* Return truth value whether we find (set (mem:M (non_stackpointer_address) -+ ...)) in instruction-pattern `body'. -+ Here we assume, that addressing with the stackpointer accesses neither -+ uncached-aliased nor invalid memory. -+ (May be, this applies to the global pointer and frame pointer also, -+ but its saver not to assume it. And probably it's not worthwile to -+ regard these registers) -+ -+ Speculative loads from invalid addresses also cause bus errors... -+ So check for (set (reg:M ...) (mem:M (non_stackpointer_address))) -+ too, unless there is an enhanced bus-error handler. */ -+ -+static int -+check_p_pattern_for_store (rtx *body, void *data) -+{ -+ if (*body && GET_CODE (*body) == SET) -+ { -+ /* Cache-barriers for SET_SRC may be requested as well. */ -+ if (!(TARGET_R10K_SPECEX & 2)) -+ body = &SET_DEST(*body); -+ -+ if (for_each_rtx (body, check_p_mem_expr, 0)) -+ return 1; -+ -+ /* Don't traverse sub-expressions again. */ -+ return -1; -+ } -+ return 0; -+} -+ -+static int -+strmatch (const char *txt, const char *match) -+{ -+ return !strncmp(txt, match, strlen (match)); -+} -+ -+/* Check for (ins (set (mem:M (dangerous_address)) ...)) or end of the -+ current basic block in instruction `insn'. -+ `state': (internal) recursion-counter and delayslot-flag -+ Criteria to recognize end-of/next basic-block are reduplicated here -+ from final_scan_insn. -+ return >0: `insn' is critical. -+ return <0: `insn' is at end of current basic-block. -+ return 0: `insn' can be ignored. */ -+ -+static int -+check_insn_for_store (int state, rtx insn) -+{ -+ rtx body; -+ -+ if (INSN_DELETED_P (insn)) -+ return 0; -+ -+ if (LABEL_P (insn)) -+ return -1; -+ -+ if (CALL_P (insn) || JUMP_P (insn) || NONJUMP_INSN_P (insn)) -+ { -+ body = PATTERN (insn); -+ if (GET_CODE (body) == SEQUENCE) -+ { -+ /* A delayed-branch sequence. */ -+ rtx insq; -+ FOR_EACH_SUBINSN(insq, insn) -+ if (! INSN_DELETED_P (insq)) -+ { -+ /* |1: delay-slot completely contained in sequence. */ -+ if (check_insn_for_store (8+state|1, insq) > 0) -+ return 1; -+ } -+ /* Following a (conditional) branch sequence, we have a new -+ basic block. */ -+ if (JUMP_P (SEQ_BEGIN(insn))) -+ return -1; -+ /* Handle a call sequence like a conditional branch sequence. */ -+ if (CALL_P (SEQ_BEGIN(insn))) -+ return -1; -+ } -+ if (GET_CODE (body) == PARALLEL) -+ if (for_each_rtx (&body, check_p_pattern_for_store, 0)) -+ return 1; -+ -+ /* Now, only a `simple' INSN or JUMP_INSN remains to be checked. */ -+ if (NONJUMP_INSN_P (insn)) -+ { -+ /* Since we don't know what's inside, we must take inline -+ assembly to be dangerous. */ -+ if (GET_CODE (body) == ASM_INPUT) -+ { -+ const char *t = XSTR (body, 0); -+ if (t && !strmatch(t, ASM_R10K_CACHE_BARRIER)) -+ return 1; -+ } -+ -+ if (check_p_pattern_for_store (&body, 0) > 0) -+ return 1; -+ } -+ /* Handle a CALL_INSN instruction like a conditional branch. */ -+ if (JUMP_P (insn) || CALL_P (insn)) -+ { -+ /* Following a (conditional) branch, we have a new basic block. */ -+ /* But check insn(s) in delay-slot first. If we could know in -+ advance that this jump is in `.reorder' mode, where gas will -+ insert a `nop' into the delay-slot, we could skip this test. -+ Since we don't know, always assume `.noreorder', sometimes -+ emitting a cache-barrier, that isn't needed. */ -+ /* But if we are here recursively, already checking a (pseudo-) -+ delay-slot, we are done. */ -+ if ( !(state & 1) ) -+ for (insn = NEXT_INSN (insn); insn; insn = NEXT_INSN (insn)) -+ { -+ if (LABEL_P (insn) || CALL_P (insn) || JUMP_P (insn)) -+ /* Not in delay-slot at all. */ -+ break; -+ -+ if (NONJUMP_INSN_P (insn)) -+ { -+ if (GET_CODE (PATTERN (insn)) == SEQUENCE) -+ /* Not in delay-slot at all. */ -+ break; -+ -+ if (check_insn_for_store (8+state|1, insn) > 0) -+ return 1; -+ /* We're done anyway. */ -+ break; -+ } -+ /* skip NOTE,... */; -+ } -+ return -1; -+ } -+ } -+ return 0; -+} -+ -+ -+/* Scan a basic block, starting with `insn', for a possibly harmful store -+ instruction. If found, output a cache barrier at the start of this -+ block. */ -+ -+static int -+bb_insert_store_cache_barrier (rtx head, rtx nxtb) -+{ -+ rtx insn = head; -+ -+ if (!insn || insn == nxtb) -+ return 0; -+ -+ while ((insn = NEXT_INSN (insn)) && insn != nxtb) -+ { -+ int found; -+ -+ if (NOTE_INSN_BASIC_BLOCK_P(insn)) /* See scan_1_bb_for_store() */ -+ break; -+ -+ found = check_insn_for_store (0, insn); -+ if (found < 0) -+ break; -+ if (found > 0) -+ { -+ /* found critical store instruction */ -+ insn = gen_rtx_ASM_INPUT (VOIDmode, -+ ASM_R10K_CACHE_BARRIER "\t" -+ ASM_COMMENT_START " Cache Barrier"); -+ /* Here we rely on the assumption, that an explicit delay-slot -+ - if any - is already embedded (in a sequence) in 'head'! */ -+ insn = emit_insn_after (insn, head); -+ return 1; -+ } -+ } -+ return 0; -+} -+ -+ -+/* Scan one basic block for a possibly harmful store instruction. -+ If found, insert a cache barrier at the start of this block, -+ return number of inserted cache_barriers. */ -+ -+static int -+scan_1_bb_for_store (rtx head, rtx end) -+{ -+ rtx nxtb; -+ int count; -+ gcc_assert (head); -+ gcc_assert (end); -+ -+ /* Note: 'end' is not necessarily reached from 'head' (hidden in -+ SEQUENCE, PARALLEL), but 'nxtb' is. */ -+ nxtb = NEXT_INSN (end); -+ -+ /* Each basic block starts with zero or more CODE_LABEL(s), followed -+ by one NOTE_INSN_BASIC_BLOCK. -+ Note: bb_head may equal next_insn(bb_end) already ! */ -+ while (head && head != nxtb && LABEL_P (head)) -+ head = NEXT_INSN (head); -+ -+ if (!head || head == nxtb) -+ return 0; -+ -+ /* Handle the basic block itself, at most up to next CALL_INSN. */ -+ count = bb_insert_store_cache_barrier (head, nxtb); -+ -+ /* 1) Handle any CALL_INSN instruction like a conditional branch. -+ 2) There may be "basic blocks" in the list, which are no basic blocks -+ at all. (containing CODE_LABELs in the body or gathering several -+ other basic blocks (e.g. bb5 containing bb6,bb7,bb8)). */ -+ -+ while ((head = NEXT_INSN (head)) && head != nxtb) -+ { -+ if (INSN_DELETED_P (head)) -+ continue; -+ -+ /* Later we'll be called again for this bb on its own. */ -+ if (NOTE_INSN_BASIC_BLOCK_P(head)) -+ break; -+ -+ if (CALL_P (SEQ_BEGIN (head)) || LABEL_P (head)) -+ count += bb_insert_store_cache_barrier (head, nxtb); -+ } -+ return count; -+} -+ -+static int -+r10k_insert_cache_barriers (void) -+{ -+ if (TARGET_R10K_SPECEX) -+ { -+ basic_block bb; -+ -+ FOR_EACH_BB (bb) -+ if (0 <= bb->index) -+ scan_1_bb_for_store (BB_HEAD (bb), BB_END (bb)); -+ } -+ return 0; -+} |