summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJoshua Kinard <kumba@gentoo.org>2005-01-09 19:14:57 +0000
committerJoshua Kinard <kumba@gentoo.org>2005-01-09 19:14:57 +0000
commit22d6bb15496015a2f5d7d53c31499f8fae252733 (patch)
treea0a71d5d297a34944ecff540b5853fc3e744b4cc /sys-devel/gcc-mips64/files
parentchanging back to virtual. if this causes problems, then please look at changi... (diff)
downloadgentoo-2-22d6bb15496015a2f5d7d53c31499f8fae252733.tar.gz
gentoo-2-22d6bb15496015a2f5d7d53c31499f8fae252733.tar.bz2
gentoo-2-22d6bb15496015a2f5d7d53c31499f8fae252733.zip
Add ip28 cache barrier patch for gcc-mips64. Anyone using this probably has an inkling of what it does. Only used in this case for kernels. The system gcc can use it for other things is absolutely needed.
Diffstat (limited to 'sys-devel/gcc-mips64/files')
-rw-r--r--sys-devel/gcc-mips64/files/digest-gcc-mips64-3.4.3-r1 (renamed from sys-devel/gcc-mips64/files/digest-gcc-mips64-3.4.3)0
-rw-r--r--sys-devel/gcc-mips64/files/gcc-3.4.2-mips-ip28_cache_barriers.patch392
2 files changed, 392 insertions, 0 deletions
diff --git a/sys-devel/gcc-mips64/files/digest-gcc-mips64-3.4.3 b/sys-devel/gcc-mips64/files/digest-gcc-mips64-3.4.3-r1
index a7535796098b..a7535796098b 100644
--- a/sys-devel/gcc-mips64/files/digest-gcc-mips64-3.4.3
+++ b/sys-devel/gcc-mips64/files/digest-gcc-mips64-3.4.3-r1
diff --git a/sys-devel/gcc-mips64/files/gcc-3.4.2-mips-ip28_cache_barriers.patch b/sys-devel/gcc-mips64/files/gcc-3.4.2-mips-ip28_cache_barriers.patch
new file mode 100644
index 000000000000..38b183288ba9
--- /dev/null
+++ b/sys-devel/gcc-mips64/files/gcc-3.4.2-mips-ip28_cache_barriers.patch
@@ -0,0 +1,392 @@
+--- gcc-3.4.2/gcc/config/mips/mips.h Thu Jul 15 02:42:47 2004
++++ gcc-3.4.2/gcc/config/mips/mips.h Sat Sep 18 00:41:48 2004
+@@ -122,6 +122,7 @@
+ extern const char *mips_isa_string; /* for -mips{1,2,3,4} */
+ extern const char *mips_abi_string; /* for -mabi={32,n32,64} */
+ extern const char *mips_cache_flush_func;/* for -mflush-func= and -mno-flush-func */
++extern const char *mips_ip28_cache_barrier;/* for -mip28-cache-barrier */
+ extern int mips_string_length; /* length of strings for mips16 */
+ extern const struct mips_cpu_info mips_cpu_info_table[];
+ extern const struct mips_cpu_info *mips_arch_info;
+@@ -333,6 +334,7 @@
+ #define TARGET_MIPS9000 (mips_arch == PROCESSOR_R9000)
+ #define TARGET_SB1 (mips_arch == PROCESSOR_SB1)
+ #define TARGET_SR71K (mips_arch == PROCESSOR_SR71000)
++#define TARGET_IP28 (mips_ip28_cache_barrier != 0)
+
+ /* Scheduling target defines. */
+ #define TUNE_MIPS3000 (mips_tune == PROCESSOR_R3000)
+@@ -752,6 +754,8 @@
+ N_("Don't call any cache flush functions"), 0}, \
+ { "flush-func=", &mips_cache_flush_func, \
+ N_("Specify cache flush function"), 0}, \
++ { "ip28-cache-barrier", &mips_ip28_cache_barrier, \
++ N_("Generate special cache barriers for SGI Indigo2 R10k"), 0}, \
+ }
+
+ /* This is meant to be redefined in the host dependent files. */
+@@ -3448,3 +3452,11 @@
+ " TEXT_SECTION_ASM_OP);
+ #endif
+ #endif
++
++#define ASM_OUTPUT_R10K_CACHE_BARRIER(STREAM) \
++ fprintf (STREAM, "\tcache 0x14,0($sp)\t%s Cache Barrier\n", ASM_COMMENT_START)
++
++/*
++ * mips.h Thu Jul 15 02:42:47 2004
++ * mips.h Fri Sep 17 23:18:19 2004 ip28
++ */
+--- gcc-3.4.2/gcc/config/mips/mips.c Wed Jul 7 21:21:10 2004
++++ gcc-3.4.2/gcc/config/mips/mips.c Fri Sep 17 23:33:44 2004
+@@ -502,6 +502,11 @@
+
+ const char *mips_cache_flush_func = CACHE_FLUSH_FUNC;
+
++/* Nonzero means generate special cache barriers to inhibit speculative
++ stores which might endanger cache coherency or reference invalid
++ addresses (especially on SGI's Indigo2 R10k (IP28)). */
++const char *mips_ip28_cache_barrier;
++
+ /* If TRUE, we split addresses into their high and low parts in the RTL. */
+ int mips_split_addresses;
+
+@@ -9676,3 +9681,7 @@
+ #endif /* TARGET_IRIX */
+
+ #include "gt-mips.h"
++/*
++ * mips.c Wed Jul 7 21:21:10 2004
++ * mips.c Fri Sep 17 23:25:53 2004 ip28
++ */
+--- gcc-3.4.2/gcc/final.c Sun Jan 18 23:39:57 2004
++++ gcc-3.4.2/gcc/final.c Fri Nov 19 00:40:50 2004
+@@ -146,6 +146,13 @@
+
+ static rtx last_ignored_compare = 0;
+
++/* Flag indicating this insn is the start of a new basic block. */
++
++#define NEW_BLOCK_LABEL 1
++#define NEW_BLOCK_BRANCH 2
++
++static int new_block = NEW_BLOCK_LABEL;
++
+ /* Assign a unique number to each insn that is output.
+ This can be used to generate unique local labels. */
+
+@@ -235,6 +242,7 @@
+ #ifdef HAVE_ATTR_length
+ static int align_fuzz (rtx, rtx, int, unsigned);
+ #endif
++static int output_store_cache_barrier (FILE *, rtx);
+
+ /* Initialize data in final at the beginning of a compilation. */
+
+@@ -1505,6 +1513,7 @@
+ int seen = 0;
+
+ last_ignored_compare = 0;
++ new_block = NEW_BLOCK_LABEL;
+
+ #ifdef SDB_DEBUGGING_INFO
+ /* When producing SDB debugging info, delete troublesome line number
+@@ -1571,6 +1580,7 @@
+
+ insn = final_scan_insn (insn, file, optimize, prescan, 0, &seen);
+ }
++ new_block = 0;
+ }
+
+ const char *
+@@ -1851,6 +1861,7 @@
+ #endif
+ if (prescan > 0)
+ break;
++ new_block = NEW_BLOCK_LABEL;
+
+ if (LABEL_NAME (insn))
+ (*debug_hooks->label) (insn);
+@@ -2009,6 +2020,26 @@
+
+ break;
+ }
++
++#ifdef TARGET_IP28
++ if (new_block)
++ {
++ /* .reorder: not really in the branch-delay-slot. */
++ if (! set_noreorder)
++ new_block = NEW_BLOCK_LABEL;
++
++ if (new_block == NEW_BLOCK_BRANCH)
++ /* Not yet, only *after* the branch-delay-slot ! */
++ new_block = NEW_BLOCK_LABEL;
++ else
++ {
++ if (TARGET_IP28)
++ output_store_cache_barrier (file, insn);
++ new_block = 0;
++ }
++ }
++#endif
++
+ /* Output this line note if it is the first or the last line
+ note in a row. */
+ if (notice_source_line (insn))
+@@ -2132,8 +2163,29 @@
+ clobbered by the function. */
+ if (GET_CODE (XVECEXP (body, 0, 0)) == CALL_INSN)
+ {
++#ifdef TARGET_IP28
++ if (TARGET_IP28)
++ new_block = NEW_BLOCK_LABEL;
++#endif
+ CC_STATUS_INIT;
+ }
++#ifdef TARGET_IP28
++ /* Following a conditional branch sequence, we have a new basic
++ block. */
++ if (TARGET_IP28)
++ {
++ rtx insn = XVECEXP (body, 0, 0);
++ rtx body = PATTERN (insn);
++
++ if ((GET_CODE (insn) == JUMP_INSN && GET_CODE (body) == SET
++ && GET_CODE (SET_SRC (body)) != LABEL_REF)
++ || (GET_CODE (insn) == JUMP_INSN
++ && GET_CODE (body) == PARALLEL
++ && GET_CODE (XVECEXP (body, 0, 0)) == SET
++ && GET_CODE (SET_SRC (XVECEXP (body, 0, 0))) != LABEL_REF))
++ new_block = NEW_BLOCK_LABEL;
++ }
++#endif
+ break;
+ }
+
+@@ -2188,6 +2240,20 @@
+ }
+ #endif
+
++#ifdef TARGET_IP28
++ /* Following a conditional branch, we have a new basic block.
++ But if we are inside a sequence, the new block starts after the
++ last insn of the sequence. */
++ if (TARGET_IP28 && final_sequence == 0
++ && (GET_CODE (insn) == CALL_INSN
++ || (GET_CODE (insn) == JUMP_INSN && GET_CODE (body) == SET
++ && GET_CODE (SET_SRC (body)) != LABEL_REF)
++ || (GET_CODE (insn) == JUMP_INSN && GET_CODE (body) == PARALLEL
++ && GET_CODE (XVECEXP (body, 0, 0)) == SET
++ && GET_CODE (SET_SRC (XVECEXP (body, 0, 0))) != LABEL_REF)))
++ new_block = NEW_BLOCK_BRANCH;
++#endif
++
+ #ifndef STACK_REGS
+ /* Don't bother outputting obvious no-ops, even without -O.
+ This optimization is fast and doesn't interfere with debugging.
+@@ -2402,6 +2468,7 @@
+
+ if (prev_nonnote_insn (insn) != last_ignored_compare)
+ abort ();
++ new_block = 0;
+
+ /* We have already processed the notes between the setter and
+ the user. Make sure we don't process them again, this is
+@@ -2435,6 +2502,7 @@
+ abort ();
+ #endif
+
++ new_block = 0;
+ return new;
+ }
+
+@@ -3866,3 +3934,188 @@
+ symbol_queue_size = 0;
+ }
+ }
++
++
++#ifdef TARGET_IP28
++
++/* Check, whether `insn' is a possibly harmful store instruction, i.e.
++ a store which might cause damage, if speculatively executed. */
++
++static int /*inline*/
++check_pattern_for_store (rtx body)
++{
++ /* Check for (set (mem:M (non_stackpointer_address) ...)). 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) */
++
++ if (body && GET_CODE (body) == SET)
++ {
++ rtx xexp = SET_DEST (body);
++ if (GET_CODE (xexp) == MEM)
++ {
++ /* Check for the most common stackpointer-addressing modes.
++ It's not worthwile to avoid a cache barrier also on the
++ remaining unfrequently used modes. */
++ xexp = XEXP (xexp, 0);
++ switch (GET_CODE (xexp))
++ {
++ case REG:
++ if (REGNO (xexp) == STACK_POINTER_REGNUM)
++ return 0;
++ break;
++ case PLUS: case MINUS: /* always `SP + const' ? */
++ if (GET_CODE (XEXP (xexp, 0)) == REG
++ && REGNO (XEXP (xexp, 0)) == STACK_POINTER_REGNUM)
++ return 0;
++ if (GET_CODE (XEXP (xexp, 1)) == REG
++ && REGNO (XEXP (xexp, 1)) == STACK_POINTER_REGNUM)
++ return 0;
++ }
++ return 1;
++ }
++ }
++ return 0;
++}
++
++static int
++check_insn_for_store (int state, rtx insn)
++{
++ /* Check for (ins (set (mem:M (dangerous_address)) ...)) or end of the
++ current basic block.
++ Criteria to recognize end-of/next basic-block are reduplicated here
++ from final_scan_insn. */
++
++ rtx body;
++ int code;
++
++ if (INSN_DELETED_P (insn))
++ return 0;
++
++ switch (code = GET_CODE (insn))
++ {
++ case CODE_LABEL:
++ return -1;
++ case CALL_INSN:
++ case JUMP_INSN:
++ case INSN:
++ body = PATTERN (insn);
++ if (GET_CODE (body) == SEQUENCE)
++ {
++ /* A delayed-branch sequence */
++ rtx ins0 = XVECEXP (body, 0, 0);
++ rtx pat0 = PATTERN (ins0);
++ int i;
++ for (i = 0; i < XVECLEN (body, 0); i++)
++ {
++ rtx insq = XVECEXP (body, 0, i);
++ if (! INSN_DELETED_P (insq))
++ {
++ int j = check_insn_for_store (state|1, insq);
++ if (j)
++ return j;
++ }
++ }
++ /* Following a conditional branch sequence, we have a new
++ basic block. */
++ if (GET_CODE (ins0) == JUMP_INSN)
++ if ((GET_CODE (pat0) == SET
++ && GET_CODE (SET_SRC (pat0)) != LABEL_REF)
++ || (GET_CODE (pat0) == PARALLEL
++ && GET_CODE (XVECEXP (pat0, 0, 0)) == SET
++ && GET_CODE (SET_SRC (XVECEXP (pat0, 0, 0))) != LABEL_REF))
++ return -1;
++ /* Handle a call sequence like a conditional branch sequence */
++ if (GET_CODE (ins0) == CALL_INSN)
++ return -1;
++ break;
++ }
++ if (GET_CODE (body) == PARALLEL)
++ {
++ int i;
++ for (i = 0; i < XVECLEN (body, 0); i++)
++ if (check_pattern_for_store (XVECEXP (body, 0, i)))
++ return 1;
++ }
++ /* Now, only a `simple' INSN or JUMP_INSN remains to be checked. */
++ if (code == INSN)
++ if (check_pattern_for_store (body))
++ return 1;
++ /* Handle a CALL_INSN instruction like a conditional branch */
++ if (code == JUMP_INSN || code == CALL_INSN)
++ {
++ /* Following a conditional branch, we have a new basic block. */
++ int ckds = 0;
++ if (code == CALL_INSN)
++ ckds = 1;
++ else
++ {
++ code = GET_CODE (body);
++ if ((code == SET
++ && GET_CODE (SET_SRC (body)) != LABEL_REF)
++ || (code == PARALLEL
++ && GET_CODE (XVECEXP (body, 0, 0)) == SET
++ && GET_CODE (SET_SRC (XVECEXP (body, 0, 0))) != LABEL_REF))
++ ckds = 1;
++ }
++ if (ckds)
++ {
++ /* 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 & 2) )
++ for (insn = NEXT_INSN (insn); insn; insn = NEXT_INSN (insn))
++ switch (GET_CODE (insn))
++ {
++ case INSN:
++ if (check_insn_for_store (state|1|2, insn) > 0)
++ return 1;
++ case CODE_LABEL:
++ case CALL_INSN:
++ case JUMP_INSN:
++ return -1;
++ default:
++ /* skip NOTE,... */;
++ }
++ return -1;
++ }
++ }
++ /*break*/
++ }
++ 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
++output_store_cache_barrier (FILE *file, rtx insn)
++{
++ for (; insn; insn = NEXT_INSN (insn))
++ {
++ int found = check_insn_for_store (0, insn);
++ if (found < 0)
++ break;
++ if (found > 0)
++ {
++ /* found critical store instruction */
++ ASM_OUTPUT_R10K_CACHE_BARRIER(file);
++ return 1;
++ }
++ }
++ fprintf(file, "\t%s Cache Barrier omitted.\n", ASM_COMMENT_START);
++ return 0;
++}
++
++#endif /* TARGET_IP28 */
++
++/*
++ * final.c Sun Jan 18 23:39:57 2004
++ * final.c Sat Sep 18 00:23:34 2004 ip28
++ */