diff options
author | Richard Henderson <rth@gcc.gnu.org> | 1999-01-06 19:18:28 -0800 |
---|---|---|
committer | Richard Henderson <rth@gcc.gnu.org> | 1999-01-06 19:18:28 -0800 |
commit | 8947065c4433a12febf38644b041e32081825000 (patch) | |
tree | c4682cc19df3771080fc19efa4aad62918b35228 /gcc | |
parent | 4ddb3ea6f72010459858f5ec470578481d2f7274 (diff) | |
download | gcc-8947065c4433a12febf38644b041e32081825000.zip gcc-8947065c4433a12febf38644b041e32081825000.tar.gz gcc-8947065c4433a12febf38644b041e32081825000.tar.bz2 |
sparc.h (PREFERRED_RELOAD_CLASS): Select GENERAL_REGS for integer data not destined for fp regs.
* sparc.h (PREFERRED_RELOAD_CLASS): Select GENERAL_REGS for
integer data not destined for fp regs.
(LEGITIMIZE_RELOAD_ADDRESS): New.
Thu Jan 7 03:03:42 1999 Stan Cox <scox@cygnus.com>
Richard Henderson <rth@cygnus.com>
Support for Hypersparc and Sparclite86x:
* sparc.h (TARGET_CPU_hypersparc, TARGET_CPU_sparclite86x): New.
(CPP_CPU32_DEFAULT_SPEC): Fix up for the new targets.
(ASM_CPU32_DEFAULT_SPEC): Likewise.
(TARGET_CPU_DEFAULT): Likewise.
(enum processor_type): Likewise.
(CPP_ENDIAN_SPEC): Handle little endian data.
(LIBGCC2_WORDS_BIG_ENDIAN): Likewise.
(ADJUST_COST): Call sparc_adjust_cost.
* sparc.c (sparc_override_options): Fix up for the new targets.
(supersparc_adjust_cost): Make static.
(hypersparc_adjust_cost): New.
(ultrasparc_adjust_cost): Make static.
(sparc_adjust_cost): New.
* sparc.md (attr cpu): Add hypersparc and sparclite86x.
(function_unit): Add hypersparc scheduling rules.
* configure.in (with_cpu handler): Recognize hypersparc.
From-SVN: r24556
Diffstat (limited to 'gcc')
-rw-r--r-- | gcc/ChangeLog | 28 | ||||
-rw-r--r-- | gcc/config/sparc/sparc.c | 415 | ||||
-rw-r--r-- | gcc/config/sparc/sparc.h | 98 | ||||
-rw-r--r-- | gcc/config/sparc/sparc.md | 49 | ||||
-rwxr-xr-x | gcc/configure | 2 | ||||
-rw-r--r-- | gcc/configure.in | 2 |
6 files changed, 421 insertions, 173 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog index 54197b2..5493f51 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,31 @@ +Thu Jan 7 03:08:17 1999 Richard Henderson <rth@cygnus.com> + + * sparc.h (PREFERRED_RELOAD_CLASS): Select GENERAL_REGS for + integer data not destined for fp regs. + (LEGITIMIZE_RELOAD_ADDRESS): New. + +Thu Jan 7 03:03:42 1999 Stan Cox <scox@cygnus.com> + Richard Henderson <rth@cygnus.com> + + Support for Hypersparc and Sparclite86x: + * sparc.h (TARGET_CPU_hypersparc, TARGET_CPU_sparclite86x): New. + (CPP_CPU32_DEFAULT_SPEC): Fix up for the new targets. + (ASM_CPU32_DEFAULT_SPEC): Likewise. + (TARGET_CPU_DEFAULT): Likewise. + (enum processor_type): Likewise. + (CPP_ENDIAN_SPEC): Handle little endian data. + (LIBGCC2_WORDS_BIG_ENDIAN): Likewise. + (ADJUST_COST): Call sparc_adjust_cost. + * sparc.c (sparc_override_options): Fix up for the new targets. + (supersparc_adjust_cost): Make static. + (hypersparc_adjust_cost): New. + (ultrasparc_adjust_cost): Make static. + (sparc_adjust_cost): New. + * sparc.md (attr cpu): Add hypersparc and sparclite86x. + (function_unit): Add hypersparc scheduling rules. + + * configure.in (with_cpu handler): Recognize hypersparc. + Thu Jan 7 23:54:05 1999 Michael Hayes <m.hayes@elec.canterbury.ac.nz> * config/c4x/c4x.c: Added space after negation operator. diff --git a/gcc/config/sparc/sparc.c b/gcc/config/sparc/sparc.c index 2748a9a..a538070 100644 --- a/gcc/config/sparc/sparc.c +++ b/gcc/config/sparc/sparc.c @@ -110,6 +110,11 @@ static void build_big_number PROTO((FILE *, int, char *)); static int function_arg_slotno PROTO((const CUMULATIVE_ARGS *, enum machine_mode, tree, int, int, int *, int *)); + +static int supersparc_adjust_cost PROTO((rtx, rtx, rtx, int)); +static int hypersparc_adjust_cost PROTO((rtx, rtx, rtx, int)); +static int ultrasparc_adjust_cost PROTO((rtx, rtx, rtx, int)); + static void sparc_output_addr_vec PROTO((rtx)); static void sparc_output_addr_diff_vec PROTO((rtx)); static void sparc_output_deferred_case_vectors PROTO((void)); @@ -176,6 +181,8 @@ sparc_override_options () { TARGET_CPU_sparclet, "tsc701" }, { TARGET_CPU_sparclite, "f930" }, { TARGET_CPU_v8, "v8" }, + { TARGET_CPU_hypersparc, "hypersparc" }, + { TARGET_CPU_sparclite86x, "sparclite86x" }, { TARGET_CPU_supersparc, "supersparc" }, { TARGET_CPU_v9, "v9" }, { TARGET_CPU_ultrasparc, "ultrasparc" }, @@ -199,6 +206,8 @@ sparc_override_options () The Fujitsu MB86934 is the recent sparclite chip, with an fpu. */ { "f930", PROCESSOR_F930, MASK_ISA|MASK_FPU, MASK_SPARCLITE }, { "f934", PROCESSOR_F934, MASK_ISA, MASK_SPARCLITE|MASK_FPU }, + { "hypersparc", PROCESSOR_HYPERSPARC, MASK_ISA, MASK_V8|MASK_FPU }, + { "sparclite86x", PROCESSOR_SPARCLITE86X, MASK_ISA|MASK_FPU, MASK_V8 }, { "sparclet", PROCESSOR_SPARCLET, MASK_ISA, MASK_SPARCLET }, /* TEMIC sparclet */ { "tsc701", PROCESSOR_TSC701, MASK_ISA, MASK_SPARCLET }, @@ -6194,7 +6203,7 @@ sparc_flat_eligible_for_epilogue_delay (trial, slot) /* Adjust the cost of a scheduling dependency. Return the new cost of a dependency LINK or INSN on DEP_INSN. COST is the current cost. */ -int +static int supersparc_adjust_cost (insn, link, dep_insn, cost) rtx insn; rtx link; @@ -6259,6 +6268,261 @@ supersparc_adjust_cost (insn, link, dep_insn, cost) return cost; } +static int +hypersparc_adjust_cost (insn, link, dep_insn, cost) + rtx insn; + rtx link; + rtx dep_insn; + int cost; +{ + enum attr_type insn_type, dep_type; + rtx pat = PATTERN(insn); + rtx dep_pat = PATTERN (dep_insn); + + if (recog_memoized (insn) < 0 || recog_memoized (dep_insn) < 0) + return cost; + + insn_type = get_attr_type (insn); + dep_type = get_attr_type (dep_insn); + + switch (REG_NOTE_KIND (link)) + { + case 0: + /* Data dependency; DEP_INSN writes a register that INSN reads some + cycles later. */ + + switch (insn_type) + { + case TYPE_STORE: + case TYPE_FPSTORE: + /* Get the delay iff the address of the store is the dependence. */ + if (GET_CODE (pat) != SET || GET_CODE (dep_pat) != SET) + return cost; + + if (rtx_equal_p (SET_DEST (dep_pat), SET_SRC (pat))) + return cost; + return cost + 3; + + case TYPE_LOAD: + case TYPE_SLOAD: + case TYPE_FPLOAD: + /* If a load, then the dependence must be on the memory address. If + the addresses aren't equal, then it might be a false dependency */ + if (dep_type == TYPE_STORE || dep_type == TYPE_FPSTORE) + { + if (GET_CODE (pat) != SET || GET_CODE (dep_pat) != SET + || GET_CODE (SET_DEST (dep_pat)) != MEM + || GET_CODE (SET_SRC (pat)) != MEM + || ! rtx_equal_p (XEXP (SET_DEST (dep_pat), 0), + XEXP (SET_SRC (pat), 0))) + return cost + 2; + + return cost + 8; + } + break; + + case TYPE_BRANCH: + /* Compare to branch latency is 0. There is no benefit from + separating compare and branch. */ + if (dep_type == TYPE_COMPARE) + return 0; + /* Floating point compare to branch latency is less than + compare to conditional move. */ + if (dep_type == TYPE_FPCMP) + return cost - 1; + break; + } + break; + + case REG_DEP_ANTI: + /* Anti-dependencies only penalize the fpu unit. */ + if (insn_type == TYPE_IALU || insn_type == TYPE_SHIFT) + return 0; + break; + + default: + break; + } + + return cost; +} + +static int +ultrasparc_adjust_cost (insn, link, dep_insn, cost) + rtx insn; + rtx link; + rtx dep_insn; + int cost; +{ + enum attr_type insn_type, dep_type; + rtx pat = PATTERN(insn); + rtx dep_pat = PATTERN (dep_insn); + + if (recog_memoized (insn) < 0 || recog_memoized (dep_insn) < 0) + return cost; + + insn_type = get_attr_type (insn); + dep_type = get_attr_type (dep_insn); + + /* Nothing issues in parallel with integer multiplies, so + mark as zero cost since the scheduler can not do anything + about it. */ + if (insn_type == TYPE_IMUL) + return 0; + +#define SLOW_FP(dep_type) \ +(dep_type == TYPE_FPSQRT || dep_type == TYPE_FPDIVS || dep_type == TYPE_FPDIVD) + + switch (REG_NOTE_KIND (link)) + { + case 0: + /* Data dependency; DEP_INSN writes a register that INSN reads some + cycles later. */ + + if (dep_type == TYPE_CMOVE) + { + /* Instructions that read the result of conditional moves cannot + be in the same group or the following group. */ + return cost + 1; + } + + switch (insn_type) + { + /* UltraSPARC can dual issue a store and an instruction setting + the value stored, except for divide and square root. */ + case TYPE_FPSTORE: + if (! SLOW_FP (dep_type)) + return 0; + return cost; + + case TYPE_STORE: + if (GET_CODE (pat) != SET || GET_CODE (dep_pat) != SET) + return cost; + + if (rtx_equal_p (SET_DEST (dep_pat), SET_SRC (pat))) + /* The dependency between the two instructions is on the data + that is being stored. Assume that the address of the store + is not also dependent. */ + return 0; + return cost; + + case TYPE_LOAD: + case TYPE_SLOAD: + case TYPE_FPLOAD: + /* A load does not return data until at least 11 cycles after + a store to the same location. 3 cycles are accounted for + in the load latency; add the other 8 here. */ + if (dep_type == TYPE_STORE || dep_type == TYPE_FPSTORE) + { + /* If the addresses are not equal this may be a false + dependency because pointer aliasing could not be + determined. Add only 2 cycles in that case. 2 is + an arbitrary compromise between 8, which would cause + the scheduler to generate worse code elsewhere to + compensate for a dependency which might not really + exist, and 0. */ + if (GET_CODE (pat) != SET || GET_CODE (dep_pat) != SET + || GET_CODE (SET_SRC (pat)) != MEM + || GET_CODE (SET_DEST (dep_pat)) != MEM + || ! rtx_equal_p (XEXP (SET_SRC (pat), 0), + XEXP (SET_DEST (dep_pat), 0))) + return cost + 2; + + return cost + 8; + } + return cost; + + case TYPE_BRANCH: + /* Compare to branch latency is 0. There is no benefit from + separating compare and branch. */ + if (dep_type == TYPE_COMPARE) + return 0; + /* Floating point compare to branch latency is less than + compare to conditional move. */ + if (dep_type == TYPE_FPCMP) + return cost - 1; + return cost; + + case TYPE_FPCMOVE: + /* FMOVR class instructions can not issue in the same cycle + or the cycle after an instruction which writes any + integer register. Model this as cost 2 for dependent + instructions. */ + if ((dep_type == TYPE_IALU || dep_type == TYPE_UNARY + || dep_type == TYPE_BINARY) + && cost < 2) + return 2; + /* Otherwise check as for integer conditional moves. */ + + case TYPE_CMOVE: + /* Conditional moves involving integer registers wait until + 3 cycles after loads return data. The interlock applies + to all loads, not just dependent loads, but that is hard + to model. */ + if (dep_type == TYPE_LOAD || dep_type == TYPE_SLOAD) + return cost + 3; + return cost; + + default: + break; + } + break; + + case REG_DEP_ANTI: + /* Divide and square root lock destination registers for full latency. */ + if (! SLOW_FP (dep_type)) + return 0; + break; + + case REG_DEP_OUTPUT: + /* IEU and FPU instruction that have the same destination + register cannot be grouped together. */ + return cost + 1; + + default: + break; + } + + /* Other costs not accounted for: + - Single precision floating point loads lock the other half of + the even/odd register pair. + - Several hazards associated with ldd/std are ignored because these + instructions are rarely generated for V9. + - The floating point pipeline can not have both a single and double + precision operation active at the same time. Format conversions + and graphics instructions are given honorary double precision status. + - call and jmpl are always the first instruction in a group. */ + + return cost; + +#undef SLOW_FP +} + +int +sparc_adjust_cost(insn, link, dep, cost) + rtx insn; + rtx link; + rtx dep; + int cost; +{ + switch (sparc_cpu) + { + case PROCESSOR_SUPERSPARC: + cost = supersparc_adjust_cost (insn, link, dep, cost); + break; + case PROCESSOR_HYPERSPARC: + case PROCESSOR_SPARCLITE86X: + cost = hypersparc_adjust_cost (insn, link, dep, cost); + break; + case PROCESSOR_ULTRASPARC: + cost = ultrasparc_adjust_cost (insn, link, dep, cost); + break; + default: + break; + } + return cost; +} + /* This describes the state of the UltraSPARC pipeline during instruction scheduling. */ @@ -6990,155 +7254,6 @@ ultrasparc_sched_reorder (dump, sched_verbose, ready, n_ready) } } -int -ultrasparc_adjust_cost (insn, link, dep_insn, cost) - rtx insn; - rtx link; - rtx dep_insn; - int cost; -{ - enum attr_type insn_type, dep_type; - rtx pat = PATTERN(insn); - rtx dep_pat = PATTERN (dep_insn); - - if (recog_memoized (insn) < 0 || recog_memoized (dep_insn) < 0) - return cost; - - insn_type = get_attr_type (insn); - dep_type = get_attr_type (dep_insn); - - /* Nothing issues in parallel with integer multiplies, so - mark as zero cost since the scheduler can not do anything - about it. */ - if (insn_type == TYPE_IMUL) - return 0; - -#define SLOW_FP(dep_type) \ -(dep_type == TYPE_FPSQRT || dep_type == TYPE_FPDIVS || dep_type == TYPE_FPDIVD) - - switch (REG_NOTE_KIND (link)) - { - case 0: - /* Data dependency; DEP_INSN writes a register that INSN reads some - cycles later. */ - - if (dep_type == TYPE_CMOVE) - { - /* Instructions that read the result of conditional moves cannot - be in the same group or the following group. */ - return cost + 1; - } - - switch (insn_type) - { - /* UltraSPARC can dual issue a store and an instruction setting - the value stored, except for divide and square root. */ - case TYPE_FPSTORE: - if (! SLOW_FP (dep_type)) - return 0; - return cost; - - case TYPE_STORE: - if (GET_CODE (pat) != SET || GET_CODE (dep_pat) != SET) - return cost; - - if (rtx_equal_p (SET_DEST (dep_pat), SET_SRC (pat))) - /* The dependency between the two instructions is on the data - that is being stored. Assume that the address of the store - is not also dependent. */ - return 0; - return cost; - - case TYPE_LOAD: - case TYPE_SLOAD: - case TYPE_FPLOAD: - /* A load does not return data until at least 11 cycles after - a store to the same location. 3 cycles are accounted for - in the load latency; add the other 8 here. */ - if (dep_type == TYPE_STORE || dep_type == TYPE_FPSTORE) - { - /* If the addresses are not equal this may be a false - dependency because pointer aliasing could not be - determined. Add only 2 cycles in that case. 2 is - an arbitrary compromise between 8, which would cause - the scheduler to generate worse code elsewhere to - compensate for a dependency which might not really - exist, and 0. */ - if (GET_CODE (pat) != SET || GET_CODE (dep_pat) != SET - || GET_CODE (SET_SRC (pat)) != MEM - || GET_CODE (SET_DEST (dep_pat)) != MEM - || ! rtx_equal_p (XEXP (SET_SRC (pat), 0), - XEXP (SET_DEST (dep_pat), 0))) - return cost + 2; - - return cost + 8; - } - return cost; - - case TYPE_BRANCH: - /* Compare to branch latency is 0. There is no benefit from - separating compare and branch. */ - if (dep_type == TYPE_COMPARE) - return 0; - /* Floating point compare to branch latency is less than - compare to conditional move. */ - if (dep_type == TYPE_FPCMP) - return cost - 1; - return cost; - - case TYPE_FPCMOVE: - /* FMOVR class instructions can not issue in the same cycle - or the cycle after an instruction which writes any - integer register. Model this as cost 2 for dependent - instructions. */ - if ((dep_type == TYPE_IALU || dep_type == TYPE_UNARY - || dep_type == TYPE_BINARY) - && cost < 2) - return 2; - /* Otherwise check as for integer conditional moves. */ - - case TYPE_CMOVE: - /* Conditional moves involving integer registers wait until - 3 cycles after loads return data. The interlock applies - to all loads, not just dependent loads, but that is hard - to model. */ - if (dep_type == TYPE_LOAD || dep_type == TYPE_SLOAD) - return cost + 3; - return cost; - - default: - break; - } - break; - - case REG_DEP_ANTI: - /* Divide and square root lock destination registers for full latency. */ - if (! SLOW_FP (dep_type)) - return 0; - break; - - case REG_DEP_OUTPUT: - /* IEU and FPU instruction that have the same destination - register cannot be grouped together. */ - return cost + 1; - - default: - break; - } - - /* Other costs not accounted for: - - Single precision floating point loads lock the other half of - the even/odd register pair. - - Several hazards associated with ldd/std are ignored because these - instructions are rarely generated for V9. - - The floating point pipeline can not have both a single and double - precision operation active at the same time. Format conversions - and graphics instructions are given honorary double precision status. - - call and jmpl are always the first instruction in a group. */ - - return cost; -} - int sparc_issue_rate () { diff --git a/gcc/config/sparc/sparc.h b/gcc/config/sparc/sparc.h index a0ecb14..a71ca1b 100644 --- a/gcc/config/sparc/sparc.h +++ b/gcc/config/sparc/sparc.h @@ -106,18 +106,23 @@ extern enum cmodel sparc_cmodel; /* Values of TARGET_CPU_DEFAULT, set via -D in the Makefile, and specified by the user via --with-cpu=foo. This specifies the cpu implementation, not the architecture size. */ +/* Note that TARGET_CPU_v9 is assumed to start the list of 64-bit + capable cpu's. */ #define TARGET_CPU_sparc 0 #define TARGET_CPU_v7 0 /* alias for previous */ #define TARGET_CPU_sparclet 1 #define TARGET_CPU_sparclite 2 #define TARGET_CPU_v8 3 /* generic v8 implementation */ #define TARGET_CPU_supersparc 4 -#define TARGET_CPU_v9 5 /* generic v9 implementation */ -#define TARGET_CPU_sparcv9 5 /* alias */ -#define TARGET_CPU_sparc64 5 /* alias */ -#define TARGET_CPU_ultrasparc 6 +#define TARGET_CPU_hypersparc 5 +#define TARGET_CPU_sparclite86x 6 +#define TARGET_CPU_v9 7 /* generic v9 implementation */ +#define TARGET_CPU_sparcv9 7 /* alias */ +#define TARGET_CPU_sparc64 7 /* alias */ +#define TARGET_CPU_ultrasparc 8 -#if TARGET_CPU_DEFAULT == TARGET_CPU_v9 || TARGET_CPU_DEFAULT == TARGET_CPU_ultrasparc +#if TARGET_CPU_DEFAULT == TARGET_CPU_v9 \ + || TARGET_CPU_DEFAULT == TARGET_CPU_ultrasparc #define CPP_CPU32_DEFAULT_SPEC "" #define ASM_CPU32_DEFAULT_SPEC "" @@ -140,19 +145,37 @@ extern enum cmodel sparc_cmodel; #define CPP_CPU64_DEFAULT_SPEC "" #define ASM_CPU64_DEFAULT_SPEC "" -#if TARGET_CPU_DEFAULT == TARGET_CPU_sparc || TARGET_CPU_DEFAULT == TARGET_CPU_v8 || TARGET_CPU_DEFAULT == TARGET_CPU_supersparc +#if TARGET_CPU_DEFAULT == TARGET_CPU_sparc \ + || TARGET_CPU_DEFAULT == TARGET_CPU_v8 #define CPP_CPU32_DEFAULT_SPEC "" #define ASM_CPU32_DEFAULT_SPEC "" #endif + #if TARGET_CPU_DEFAULT == TARGET_CPU_sparclet #define CPP_CPU32_DEFAULT_SPEC "-D__sparclet__" #define ASM_CPU32_DEFAULT_SPEC "-Asparclet" #endif + #if TARGET_CPU_DEFAULT == TARGET_CPU_sparclite #define CPP_CPU32_DEFAULT_SPEC "-D__sparclite__" #define ASM_CPU32_DEFAULT_SPEC "-Asparclite" #endif +#if TARGET_CPU_DEFAULT == TARGET_CPU_supersparc +#define CPP_CPU32_DEFAULT_SPEC "-D__supersparc__ -D__sparc_v8__" +#define ASM_CPU32_DEFAULT_SPEC "" +#endif + +#if TARGET_CPU_DEFAULT == TARGET_CPU_hypersparc +#define CPP_CPU32_DEFAULT_SPEC "-D__hypersparc__ -D__sparc_v8__" +#define ASM_CPU32_DEFAULT_SPEC "" +#endif + +#if TARGET_CPU_DEFAULT == TARGET_CPU_sparclite86x +#define CPP_CPU32_DEFAULT_SPEC "-D__sparclite86x__ -D__sparc_v8__" +#define ASM_CPU32_DEFAULT_SPEC "-Av8" +#endif + #endif #if !defined(CPP_CPU32_DEFAULT_SPEC) || !defined(CPP_CPU64_DEFAULT_SPEC) @@ -208,6 +231,8 @@ Unrecognized value in TARGET_CPU_DEFAULT. %{mcpu=f930:-D__sparclite__} %{mcpu=f934:-D__sparclite__} \ %{mcpu=v8:-D__sparc_v8__} \ %{mcpu=supersparc:-D__supersparc__ -D__sparc_v8__} \ +%{mcpu=hypersparc:-D__hypersparc__ -D__sparc_v8__} \ +%{mcpu=sparclite86x:-D__sparclite86x__ -D__sparc_v8__} \ %{mcpu=v9:-D__sparc_v9__} \ %{mcpu=ultrasparc:-D__sparc_v9__} \ %{!mcpu*:%{!mcypress:%{!msparclite:%{!mf930:%{!mf934:%{!mv8:%{!msupersparc:%(cpp_cpu_default)}}}}}}} \ @@ -243,7 +268,9 @@ Unrecognized value in TARGET_CPU_DEFAULT. " /* Macros to distinguish endianness. */ -#define CPP_ENDIAN_SPEC "%{mlittle-endian:-D__LITTLE_ENDIAN__}" +#define CPP_ENDIAN_SPEC "\ +%{mlittle-endian:-D__LITTLE_ENDIAN__} \ +%{mlittle-endian-data:-D__LITTLE_ENDIAN_DATA__}" /* Macros to distinguish the particular subtarget. */ #define CPP_SUBTARGET_SPEC "" @@ -598,6 +625,8 @@ enum processor_type { PROCESSOR_SPARCLITE, PROCESSOR_F930, PROCESSOR_F934, + PROCESSOR_HYPERSPARC, + PROCESSOR_SPARCLITE86X, PROCESSOR_SPARCLET, PROCESSOR_TSC701, PROCESSOR_V9, @@ -684,7 +713,7 @@ extern int sparc_align_funcs; /* Define this to set the endianness to use in libgcc2.c, which can not depend on target_flags. */ -#if defined (__LITTLE_ENDIAN__) +#if defined (__LITTLE_ENDIAN__) || defined(__LITTLE_ENDIAN_DATA__) #define LIBGCC2_WORDS_BIG_ENDIAN 0 #else #define LIBGCC2_WORDS_BIG_ENDIAN 1 @@ -1410,15 +1439,23 @@ extern char leaf_reg_remap[]; in class CLASS, return the class of reg to actually use. In general this is just CLASS; but on some machines in some cases it is preferable to use a more restrictive class. */ -/* We can't load constants into FP registers. We can't load any FP constant - if an 'E' constraint fails to match it. */ +/* - We can't load constants into FP registers. We can't load any FP + constant if an 'E' constraint fails to match it. + - Try and reload integer constants (symbolic or otherwise) back into + registers directly, rather than having them dumped to memory. */ + #define PREFERRED_RELOAD_CLASS(X,CLASS) \ (CONSTANT_P (X) \ - && (FP_REG_CLASS_P (CLASS) \ + ? ((FP_REG_CLASS_P (CLASS) \ || (GET_MODE_CLASS (GET_MODE (X)) == MODE_FLOAT \ && (HOST_FLOAT_FORMAT != IEEE_FLOAT_FORMAT \ || HOST_BITS_PER_INT != BITS_PER_WORD))) \ - ? NO_REGS : (CLASS)) + ? NO_REGS \ + : (!FP_REG_CLASS_P (CLASS) \ + && GET_MODE_CLASS (GET_MODE (X)) == MODE_INT) \ + ? GENERAL_REGS \ + : (CLASS)) \ + : (CLASS)) /* Return the register class of a scratch register needed to load IN into a register of class CLASS in MODE. @@ -2515,6 +2552,32 @@ extern struct rtx_def *legitimize_pic_address (); if (memory_address_p (MODE, X)) \ goto WIN; } +/* Try a machine-dependent way of reloading an illegitimate address + operand. If we find one, push the reload and jump to WIN. This + macro is used in only one place: `find_reloads_address' in reload.c. + + For Sparc 32, we wish to handle addresses by splitting them into + HIGH+LO_SUM pairs, retaining the LO_SUM in the memory reference. + This cuts the number of extra insns by one. */ + +#define LEGITIMIZE_RELOAD_ADDRESS(X,MODE,OPNUM,TYPE,IND_LEVELS,WIN) \ +do { \ + /* Decompose SImode constants into hi+lo_sum. We do have to \ + rerecognize what we produce, so be careful. */ \ + if (CONSTANT_P (X) \ + && GET_MODE (X) == SImode \ + && GET_CODE (X) != LO_SUM && GET_CODE (X) != HIGH) \ + { \ + X = gen_rtx_LO_SUM (GET_MODE (X), \ + gen_rtx_HIGH (GET_MODE (X), X), X); \ + push_reload (XEXP (X, 0), NULL_RTX, &XEXP (X, 0), NULL_PTR, \ + BASE_REG_CLASS, GET_MODE (X), VOIDmode, 0, 0, \ + OPNUM, TYPE); \ + goto WIN; \ + } \ + /* ??? 64-bit reloads. */ \ +} while (0) + /* Go to LABEL if ADDR (a legitimate address expression) has an effect that depends on the machine mode it is used for. On the SPARC this is never true. */ @@ -2803,12 +2866,8 @@ extern struct rtx_def *legitimize_pic_address (); #define ISSUE_RATE sparc_issue_rate() /* Adjust the cost of dependencies. */ -#define ADJUST_COST(INSN,LINK,DEP,COST) \ - if (sparc_cpu == PROCESSOR_SUPERSPARC) \ - (COST) = supersparc_adjust_cost (INSN, LINK, DEP, COST); \ - else if (sparc_cpu == PROCESSOR_ULTRASPARC) \ - (COST) = ultrasparc_adjust_cost (INSN, LINK, DEP, COST); \ - else +#define ADJUST_COST(INSN,LINK,DEP,COST) \ + sparc_adjust_cost(INSN, LINK, DEP, COST) extern void ultrasparc_sched_reorder (); extern void ultrasparc_sched_init (); @@ -3394,11 +3453,10 @@ extern int sparc_flat_epilogue_delay_slots (); extern int sparc_issue_rate (); extern int splittable_immediate_memory_operand (); extern int splittable_symbolic_memory_operand (); -extern int supersparc_adjust_cost (); +extern int sparc_adjust_cost (); extern int symbolic_memory_operand (); extern int symbolic_operand (); extern int text_segment_operand (); -extern int ultrasparc_adjust_cost (); extern int uns_small_int (); extern int v9_regcmp_op (); extern int v9_regcmp_p (); diff --git a/gcc/config/sparc/sparc.md b/gcc/config/sparc/sparc.md index 59fcd59..2b1e518 100644 --- a/gcc/config/sparc/sparc.md +++ b/gcc/config/sparc/sparc.md @@ -65,7 +65,7 @@ ;; Attribute for cpu type. ;; These must match the values for enum processor_type in sparc.h. -(define_attr "cpu" "v7,cypress,v8,supersparc,sparclite,f930,f934,sparclet,tsc701,v9,ultrasparc" +(define_attr "cpu" "v7,cypress,v8,supersparc,sparclite,f930,f934,hypersparc,sparclite86x,sparclet,tsc701,v9,ultrasparc" (const (symbol_ref "sparc_cpu_attr"))) ;; Attribute for the instruction set. @@ -345,6 +345,53 @@ (eq_attr "type" "imul")) 4 4) +;; ----- hypersparc/sparclite86x scheduling +;; The Hypersparc can issue 1 - 2 insns per cycle. The dual issue cases are: +;; L-Ld/St I-Int F-Float B-Branch LI/LF/LB/II/IF/IB/FF/FB +;; II/FF case is only when loading a 32 bit hi/lo constant +;; Single issue insns include call, jmpl, u/smul, u/sdiv, lda, sta, fcmp +;; Memory delivers its result in one cycle to IU + +(define_function_unit "memory" 1 0 + (and (ior (eq_attr "cpu" "hypersparc") (eq_attr "cpu" "sparclite86x")) + (eq_attr "type" "load,sload,fpload")) + 1 1) + +(define_function_unit "memory" 1 0 + (and (ior (eq_attr "cpu" "hypersparc") (eq_attr "cpu" "sparclite86x")) + (eq_attr "type" "store,fpstore")) + 2 1) + +(define_function_unit "fp_alu" 1 0 + (and (ior (eq_attr "cpu" "hypersparc") (eq_attr "cpu" "sparclite86x")) + (eq_attr "type" "fp,fpmove,fpcmp")) + 1 1) + +(define_function_unit "fp_mds" 1 0 + (and (ior (eq_attr "cpu" "hypersparc") (eq_attr "cpu" "sparclite86x")) + (eq_attr "type" "fpmul")) + 1 1) + +(define_function_unit "fp_mds" 1 0 + (and (ior (eq_attr "cpu" "hypersparc") (eq_attr "cpu" "sparclite86x")) + (eq_attr "type" "fpdivs")) + 8 6) + +(define_function_unit "fp_mds" 1 0 + (and (ior (eq_attr "cpu" "hypersparc") (eq_attr "cpu" "sparclite86x")) + (eq_attr "type" "fpdivd")) + 12 10) + +(define_function_unit "fp_mds" 1 0 + (and (ior (eq_attr "cpu" "hypersparc") (eq_attr "cpu" "sparclite86x")) + (eq_attr "type" "fpsqrt")) + 17 15) + +(define_function_unit "fp_mds" 1 0 + (and (ior (eq_attr "cpu" "hypersparc") (eq_attr "cpu" "sparclite86x")) + (eq_attr "type" "imul")) + 17 15) + ;; ----- sparclet tsc701 scheduling ;; The tsc701 issues 1 insn per cycle. ;; Results may be written back out of order. diff --git a/gcc/configure b/gcc/configure index 63b5027..9e0748e 100755 --- a/gcc/configure +++ b/gcc/configure @@ -5518,7 +5518,7 @@ for machine in $build $host $target; do .) target_cpu_default2=TARGET_CPU_"`echo $machine | sed 's/-.*$//'`" ;; - .supersparc | .ultrasparc | .v7 | .v8 | .v9) + .supersparc | .hypersparc | .ultrasparc | .v7 | .v8 | .v9) target_cpu_default2="TARGET_CPU_$with_cpu" ;; *) diff --git a/gcc/configure.in b/gcc/configure.in index c77d3cd..92675af 100644 --- a/gcc/configure.in +++ b/gcc/configure.in @@ -3347,7 +3347,7 @@ changequote([,])dnl .) target_cpu_default2=TARGET_CPU_"`echo $machine | sed 's/-.*$//'`" ;; - .supersparc | .ultrasparc | .v7 | .v8 | .v9) + .supersparc | .hypersparc | .ultrasparc | .v7 | .v8 | .v9) target_cpu_default2="TARGET_CPU_$with_cpu" ;; *) |