2004-02-26 James E Wilson * mips-protos.h (mips_st_address_bypass_p, mips_ld_address_bypass_p): New. * mips.c (mips_multipass_dfa_lookahead): Declare. (mips_sb1_fp_exceptions, mips_sb1_fp_except_string): New. (TARGET_SCHED_FIRST_CYCLE_MULTIPASS_DFA_LOOKAHEAD): New. (fp_register_operand, lo_operand): New. (mips_rtx_costs): Add TUNE_SB1 support. (override_options): Handle -msb1-fp-exceptions= option. (mips_issue_rate): Add PROCESSOR_SB1 support. (mips_use_dfa_pipeline_interface): Likewise. (mips_multipass_dfa_lookahead, mips_st_address_bypass_p, mips_ld_address_bypass_p): New. * mips.h (mips_sb1_fp_except_string, mips_sb1_fp_exceptions): Declare. (TARGET_OPTIONS): Add -msb1-fp-exceptions=. (BRANCH_COST): Fix white space. (PREDICATE_CODES): Add fp_register_operand and lo_operand. * mips.md (sb_type): New. Modify many patterns to add sb_type attribute. (sb1.md): Include. * sb1.md: New file. Index: mips-protos.h =================================================================== RCS file: /services/cvs/cvsroot/sources/unstable/gcc-3.4.x/gcc/config/mips/mips-protos.h,v retrieving revision 1.1.1.1 diff -p -r1.1.1.1 mips-protos.h *** mips-protos.h 28 Jan 2004 20:55:22 -0000 1.1.1.1 --- mips-protos.h 27 Feb 2004 03:15:34 -0000 *************** extern const char *mips_output_condition *** 142,147 **** --- 142,149 ---- extern const char *mips_output_division (const char *, rtx *); extern unsigned int mips_hard_regno_nregs (int, enum machine_mode); extern int mips_return_in_memory (tree); + extern int mips_st_address_bypass_p (rtx, rtx); + extern int mips_ld_address_bypass_p (rtx, rtx); extern const char *mips_emit_prefetch (rtx *); extern void irix_asm_output_align (FILE *, unsigned); Index: mips.c =================================================================== RCS file: /services/cvs/cvsroot/sources/unstable/gcc-3.4.x/gcc/config/mips/mips.c,v retrieving revision 1.1.1.1 diff -p -r1.1.1.1 mips.c *** mips.c 28 Jan 2004 20:55:22 -0000 1.1.1.1 --- mips.c 27 Feb 2004 03:15:48 -0000 *************** static const struct mips_cpu_info *mips_ *** 281,286 **** --- 281,287 ---- static int mips_adjust_cost (rtx, rtx, rtx, int); static int mips_issue_rate (void); static int mips_use_dfa_pipeline_interface (void); + static int mips_multipass_dfa_lookahead (void); static void mips_init_libfuncs (void); static tree mips_build_builtin_va_list (void); *************** int mips16_hard_float; *** 500,505 **** --- 501,513 ---- const char *mips_cache_flush_func = CACHE_FLUSH_FUNC; + /* Whether the SB1 FP exceptions are enabled. We schedule both FP pipes + if exceptions are off, and only one if they are on. We assume they are + on by default. */ + + int mips_sb1_fp_exceptions = 1; + const char *mips_sb1_fp_except_string; /* for -msb1-fp-exceptions={on,off} */ + /* If TRUE, we split addresses into their high and low parts in the RTL. */ int mips_split_addresses; *************** const struct mips_cpu_info mips_cpu_info *** 754,759 **** --- 762,770 ---- #define TARGET_SCHED_ISSUE_RATE mips_issue_rate #undef TARGET_SCHED_USE_DFA_PIPELINE_INTERFACE #define TARGET_SCHED_USE_DFA_PIPELINE_INTERFACE mips_use_dfa_pipeline_interface + #undef TARGET_SCHED_FIRST_CYCLE_MULTIPASS_DFA_LOOKAHEAD + #define TARGET_SCHED_FIRST_CYCLE_MULTIPASS_DFA_LOOKAHEAD \ + mips_multipass_dfa_lookahead #undef TARGET_FUNCTION_OK_FOR_SIBCALL #define TARGET_FUNCTION_OK_FOR_SIBCALL mips_function_ok_for_sibcall *************** stack_operand (rtx op, enum machine_mode *** 1647,1652 **** --- 1658,1690 ---- && addr.reg == stack_pointer_rtx); } + /* Helper function for DFA schedulers. Return true if OP is a floating + point register. */ + + int + fp_register_operand (rtx op, enum machine_mode mode) + { + if (! register_operand (op, mode)) + return 0; + if (GET_CODE (op) == SUBREG) + op = SUBREG_REG (op); + if (GET_CODE (op) == REG) + { + unsigned int regno = REGNO (op); + if (regno < FIRST_PSEUDO_REGISTER) + return FP_REG_P (regno); + } + return 0; + } + + /* Helper function for DFA schedulers. Return true if OP is a LO reg. */ + + int + lo_operand (rtx op, enum machine_mode mode ATTRIBUTE_UNUSED) + { + return REG_P (op) && REGNO (op) == LO_REGNUM; + } + /* This function is used to implement GO_IF_LEGITIMATE_ADDRESS. It returns a nonzero value if X is a legitimate address for a memory *************** mips_rtx_costs (rtx x, int code, int out *** 2337,2342 **** --- 2375,2382 ---- *total = COSTS_N_INSNS (2); else if (TUNE_MIPS6000) *total = COSTS_N_INSNS (3); + else if (TUNE_SB1) + *total = COSTS_N_INSNS (4); else *total = COSTS_N_INSNS (6); return true; *************** mips_rtx_costs (rtx x, int code, int out *** 2361,2367 **** { if (TUNE_MIPS3000 || TUNE_MIPS3900 ! || TUNE_MIPS5000) *total = COSTS_N_INSNS (4); else if (TUNE_MIPS6000 || TUNE_MIPS5400 --- 2401,2408 ---- { if (TUNE_MIPS3000 || TUNE_MIPS3900 ! || TUNE_MIPS5000 ! || TUNE_SB1) *total = COSTS_N_INSNS (4); else if (TUNE_MIPS6000 || TUNE_MIPS5400 *************** mips_rtx_costs (rtx x, int code, int out *** 2374,2382 **** if (mode == DFmode) { ! if (TUNE_MIPS3000 ! || TUNE_MIPS3900 ! || TUNE_MIPS5000) *total = COSTS_N_INSNS (5); else if (TUNE_MIPS6000 || TUNE_MIPS5400 --- 2415,2425 ---- if (mode == DFmode) { ! if (TUNE_SB1) ! *total = COSTS_N_INSNS (4); ! else if (TUNE_MIPS3000 ! || TUNE_MIPS3900 ! || TUNE_MIPS5000) *total = COSTS_N_INSNS (5); else if (TUNE_MIPS6000 || TUNE_MIPS5400 *************** mips_rtx_costs (rtx x, int code, int out *** 2391,2397 **** *total = COSTS_N_INSNS (12); else if (TUNE_MIPS3900) *total = COSTS_N_INSNS (2); ! else if (TUNE_MIPS5400 || TUNE_MIPS5500) *total = COSTS_N_INSNS ((mode == DImode) ? 4 : 3); else if (TUNE_MIPS7000) *total = COSTS_N_INSNS (mode == DImode ? 9 : 5); --- 2434,2440 ---- *total = COSTS_N_INSNS (12); else if (TUNE_MIPS3900) *total = COSTS_N_INSNS (2); ! else if (TUNE_MIPS5400 || TUNE_MIPS5500 || TUNE_SB1) *total = COSTS_N_INSNS ((mode == DImode) ? 4 : 3); else if (TUNE_MIPS7000) *total = COSTS_N_INSNS (mode == DImode ? 9 : 5); *************** mips_rtx_costs (rtx x, int code, int out *** 2414,2419 **** --- 2457,2464 ---- *total = COSTS_N_INSNS (12); else if (TUNE_MIPS6000) *total = COSTS_N_INSNS (15); + else if (TUNE_SB1) + *total = COSTS_N_INSNS (24); else if (TUNE_MIPS5400 || TUNE_MIPS5500) *total = COSTS_N_INSNS (30); else *************** mips_rtx_costs (rtx x, int code, int out *** 2430,2435 **** --- 2475,2482 ---- *total = COSTS_N_INSNS (59); else if (TUNE_MIPS6000) *total = COSTS_N_INSNS (16); + else if (TUNE_SB1) + *total = COSTS_N_INSNS (32); else *total = COSTS_N_INSNS (36); return true; *************** mips_rtx_costs (rtx x, int code, int out *** 2447,2452 **** --- 2494,2501 ---- *total = COSTS_N_INSNS (36); else if (TUNE_MIPS5400 || TUNE_MIPS5500) *total = COSTS_N_INSNS ((mode == SImode) ? 42 : 74); + else if (TUNE_SB1) + *total = COSTS_N_INSNS ((mode == SImode) ? 36 : 68); else *total = COSTS_N_INSNS (69); return true; *************** override_options (void) *** 5140,5145 **** --- 5189,5206 ---- mips_hi_relocs[SYMBOL_GOTOFF_LOADGP] = "%hi(%neg(%gp_rel("; mips_lo_relocs[SYMBOL_GOTOFF_LOADGP] = "%lo(%neg(%gp_rel("; } + + /* Interpret the -msb1-fp-exceptions= option. */ + if (mips_sb1_fp_except_string != 0) + { + if (strcmp (mips_sb1_fp_except_string, "on") == 0) + mips_sb1_fp_exceptions = 1; + else if (strcmp (mips_sb1_fp_except_string, "off") == 0) + mips_sb1_fp_exceptions = 0; + else + fatal_error ("bad value (%s) for -msb1-fp-exceptions= switch", + mips_sb1_fp_except_string); + } } /* Implement CONDITIONAL_REGISTER_USAGE. */ *************** mips_return_in_memory (tree type) *** 9335,9340 **** --- 9396,9405 ---- return ((int_size_in_bytes (type) > (2 * UNITS_PER_WORD)) || (int_size_in_bytes (type) == -1)); } + + /* Instruction scheduler hooks and helper routines. */ + + /* Return the number of instructions that can be issued per cycle. */ static int mips_issue_rate (void) *************** mips_issue_rate (void) *** 9347,9352 **** --- 9412,9424 ---- case PROCESSOR_R9000: return 2; + case PROCESSOR_SB1: + /* This is actually 4, but we get better performance if we claim 3. + This is partly because of unwanted speculative code motion with the + larger number, and partly because in most common cases we can't + reach the theoretical max of 4. */ + return 3; + default: return 1; } *************** mips_use_dfa_pipeline_interface (void) *** 9367,9372 **** --- 9439,9445 ---- case PROCESSOR_R5500: case PROCESSOR_R7000: case PROCESSOR_R9000: + case PROCESSOR_SB1: case PROCESSOR_SR71000: return true; *************** mips_use_dfa_pipeline_interface (void) *** 9375,9380 **** --- 9448,9533 ---- } } + /* Implements TARGET_SCHED_FIRST_CYCLE_MULTIPASS_DFA_LOOKAHAED. Return how + many instructions the scheduler should examine when trying to determine the + best packing of pending ready instructions into issue slots. */ + + static int + mips_multipass_dfa_lookahead (void) + { + if (mips_tune == PROCESSOR_SB1) + return 4; + + return 0; + } + + /* Returns true if PRODUCER, a load instruction, produces an address for + CONSUMER, a store instruction. */ + + int + mips_st_address_bypass_p (rtx producer, rtx consumer) + { + rtx dest, reg, mem; + + if (producer == NULL_RTX || consumer == NULL_RTX) + abort (); + + /* Extract the register dest of the load. */ + dest = single_set (producer); + if (dest == NULL_RTX) + abort (); + reg = SET_DEST (dest); + if (GET_CODE (reg) == SUBREG) + reg = SUBREG_REG (reg); + if (GET_CODE (reg) != REG) + abort (); + + /* Extract the memory dest of the store. */ + dest = single_set (consumer); + if (dest == NULL_RTX) + abort (); + mem = SET_DEST (dest); + if (GET_CODE (mem) != MEM) + abort (); + + /* Check to see the reg is used in the mem. */ + return reg_mentioned_p (reg, mem); + } + + /* Returns true if PRODUCER, a load instruction, produces an address for + CONSUMER, a load or prefetch instruction. */ + + int + mips_ld_address_bypass_p (rtx producer, rtx consumer) + { + rtx dest, src, reg, mem; + + if (producer == NULL_RTX || consumer == NULL_RTX) + abort (); + + /* Extract the reg dest of the first load. */ + dest = single_set (producer); + if (dest == NULL_RTX) + abort (); + reg = SET_DEST (dest); + if (GET_CODE (reg) == SUBREG) + reg = SUBREG_REG (reg); + if (GET_CODE (reg) != REG) + abort (); + + /* Extract the mem source of the second load. */ + src = single_set (consumer); + if (src == NULL_RTX) + abort (); + mem = SET_SRC (src); + /* The MEM could be many different things here, including extracts, extends, + unspecs, etc. It doesn't seem worth the trouble to narrow this down any + further, as that would be error prone. */ + + /* Check to see the reg is used in the mem. */ + return reg_mentioned_p (reg, mem); + } + const char * mips_emit_prefetch (rtx *operands) Index: mips.h =================================================================== RCS file: /services/cvs/cvsroot/sources/unstable/gcc-3.4.x/gcc/config/mips/mips.h,v retrieving revision 1.1.1.1 diff -p -r1.1.1.1 mips.h *** mips.h 28 Jan 2004 20:55:22 -0000 1.1.1.1 --- mips.h 27 Feb 2004 03:15:54 -0000 *************** extern const char *mips_tune_string; *** 122,127 **** --- 122,129 ---- 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_sb1_fp_except_string;/* for -msb1-fp-exceptions */ + extern int mips_sb1_fp_exceptions; /* for -msb1-fp-exceptions */ 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; *************** extern const struct mips_cpu_info *mips_ *** 739,744 **** --- 741,748 ---- N_("Don't call any cache flush functions"), 0}, \ { "flush-func=", &mips_cache_flush_func, \ N_("Specify cache flush function"), 0}, \ + { "sb1-fp-exceptions=", &mips_sb1_fp_except_string, \ + N_("For SB1, specify whether FP exceptions are enabled"), 0} \ } /* This is meant to be redefined in the host dependent files. */ *************** typedef struct mips_args { *** 2715,2721 **** /* ??? Fix this to be right for the R8000. */ #define BRANCH_COST \ ((! TARGET_MIPS16 \ ! && (TUNE_MIPS4000 || TUNE_MIPS6000)) \ ? 2 : 1) /* If defined, modifies the length assigned to instruction INSN as a --- 2719,2725 ---- /* ??? Fix this to be right for the R8000. */ #define BRANCH_COST \ ((! TARGET_MIPS16 \ ! && (TUNE_MIPS4000 || TUNE_MIPS6000)) \ ? 2 : 1) /* If defined, modifies the length assigned to instruction INSN as a *************** typedef struct mips_args { *** 2776,2782 **** CONST_DOUBLE, CONST }}, \ {"fcc_register_operand", { REG, SUBREG }}, \ {"hilo_operand", { REG }}, \ ! {"extend_operator", { ZERO_EXTEND, SIGN_EXTEND }}, /* A list of predicates that do special things with modes, and so should not elicit warnings for VOIDmode match_operand. */ --- 2780,2788 ---- CONST_DOUBLE, CONST }}, \ {"fcc_register_operand", { REG, SUBREG }}, \ {"hilo_operand", { REG }}, \ ! {"extend_operator", { ZERO_EXTEND, SIGN_EXTEND }}, \ ! {"fp_register_operand", { REG, SUBREG }}, \ ! {"lo_operand", { REG }}, /* A list of predicates that do special things with modes, and so should not elicit warnings for VOIDmode match_operand. */ Index: mips.md =================================================================== RCS file: /services/cvs/cvsroot/sources/unstable/gcc-3.4.x/gcc/config/mips/mips.md,v retrieving revision 1.1.1.1 diff -p -r1.1.1.1 mips.md *** mips.md 28 Jan 2004 20:55:22 -0000 1.1.1.1 --- mips.md 27 Feb 2004 03:16:08 -0000 *************** *** 124,129 **** --- 124,141 ---- (eq_attr "got" "load") (const_string "load")] (const_string "unknown"))) + ;; Extra types needed for the SB-1 DFA scheduler description. + ;; ??? salu is const+arith+darith except shifts, slt, and clz (and trap). + ;; SB-1 does not have eb/eh, but I am guessing they would be in + ;; salu. type icmp exists above but is not used anywhere. Only mips16 + ;; has integer compare instructions. + ;; ??? There is a nop type, but the nop instruction doesn't use it. + ;; ??? darith serves no purpose. + ;; ??? Do not need type attribute on define_insn_and_split? + ;; ??? Many multi-insn patterns could be combined with following define_split. + (define_attr "sb_type" "unknown,fpidxload,fpidxstore,fpload,fpstore,clz,slt,trap,shift,icmp" + (const_string "unknown")) + ;; Main data type used by the insn (define_attr "mode" "unknown,none,QI,HI,SI,DI,SF,DF,FPSW" (const_string "unknown")) *************** *** 611,616 **** --- 623,629 ---- (include "5500.md") (include "7000.md") (include "9000.md") + (include "sb1.md") (include "sr71k.md") ;; *************** *** 632,638 **** return "break 0"; else return "break"; ! }) (define_expand "conditional_trap" [(trap_if (match_operator 0 "cmp_op" --- 645,653 ---- return "break 0"; else return "break"; ! } ! [(set_attr "sb_type" "trap")]) ! (define_expand "conditional_trap" [(trap_if (match_operator 0 "cmp_op" *************** *** 655,661 **** (match_operand:SI 2 "arith_operand" "dI")]) (const_int 0))] "ISA_HAS_COND_TRAP" ! "t%C0\t%z1,%z2") (define_insn "" [(trap_if (match_operator 0 "trap_cmp_op" --- 670,677 ---- (match_operand:SI 2 "arith_operand" "dI")]) (const_int 0))] "ISA_HAS_COND_TRAP" ! "t%C0\t%z1,%z2" ! [(set_attr "sb_type" "trap")]) (define_insn "" [(trap_if (match_operator 0 "trap_cmp_op" *************** *** 663,669 **** (match_operand:DI 2 "arith_operand" "dI")]) (const_int 0))] "TARGET_64BIT && ISA_HAS_COND_TRAP" ! "t%C0\t%z1,%z2") ;; ;; .................... --- 679,686 ---- (match_operand:DI 2 "arith_operand" "dI")]) (const_int 0))] "TARGET_64BIT && ISA_HAS_COND_TRAP" ! "t%C0\t%z1,%z2" ! [(set_attr "sb_type" "trap")]) ;; ;; .................... *************** dsrl\t%3,%3,1\n\ *** 2775,2780 **** --- 2792,2798 ---- "ISA_HAS_CLZ_CLO" "clz\t%0,%1" [(set_attr "type" "arith") + (set_attr "sb_type" "clz") (set_attr "mode" "SI")]) (define_insn "clzdi2" *************** dsrl\t%3,%3,1\n\ *** 2783,2788 **** --- 2801,2807 ---- "ISA_HAS_DCLZ_DCLO" "dclz\t%0,%1" [(set_attr "type" "arith") + (set_attr "sb_type" "clz") (set_attr "mode" "DI")]) ;; *************** dsrl\t%3,%3,1\n\ *** 3051,3056 **** --- 3070,3076 ---- cmpi\t%1,%2 cmp\t%1,%2" [(set_attr "type" "arith") + (set_attr "sb_type" "*,icmp,icmp") (set_attr "mode" "SI") (set_attr_alternative "length" [(const_int 4) *************** dsrl\t%3,%3,1\n\ *** 3093,3098 **** --- 3113,3119 ---- cmpi\t%1,%2 cmp\t%1,%2" [(set_attr "type" "arith") + (set_attr "sb_type" "*,icmp,icmp") (set_attr "mode" "DI") (set_attr_alternative "length" [(const_int 4) *************** dsrl\t%3,%3,1\n\ *** 3157,3162 **** --- 3178,3184 ---- sll\t%0,%1,0 sw\t%1,%0" [(set_attr "type" "darith,store") + (set_attr "sb_type" "shift,*") (set_attr "mode" "SI") (set_attr "extended_mips16" "yes,*")]) *************** dsrl\t%3,%3,1\n\ *** 3168,3173 **** --- 3190,3196 ---- sll\t%0,%1,0 sh\t%1,%0" [(set_attr "type" "darith,store") + (set_attr "sb_type" "shift,*") (set_attr "mode" "SI") (set_attr "extended_mips16" "yes,*")]) *************** dsrl\t%3,%3,1\n\ *** 3179,3184 **** --- 3202,3208 ---- sll\t%0,%1,0 sb\t%1,%0" [(set_attr "type" "darith,store") + (set_attr "sb_type" "shift,*") (set_attr "mode" "SI") (set_attr "extended_mips16" "yes,*")]) *************** dsrl\t%3,%3,1\n\ *** 3191,3196 **** --- 3215,3221 ---- "TARGET_64BIT && !TARGET_MIPS16 && INTVAL (operands[2]) >= 32" "dsra\t%0,%1,%2" [(set_attr "type" "darith") + (set_attr "sb_type" "shift") (set_attr "mode" "SI")]) (define_insn "" *************** dsrl\t%3,%3,1\n\ *** 3200,3205 **** --- 3225,3231 ---- "TARGET_64BIT && !TARGET_MIPS16" "dsra\t%0,%1,32" [(set_attr "type" "darith") + (set_attr "sb_type" "shift") (set_attr "mode" "SI")]) *************** dsrl\t%3,%3,1\n\ *** 3487,3492 **** --- 3513,3519 ---- sll\t%0,%1,0 lw\t%0,%1" [(set_attr "type" "arith,load") + (set_attr "sb_type" "shift,*") (set_attr "mode" "DI") (set_attr "extended_mips16" "yes,*")]) *************** dsrl\t%3,%3,1\n\ *** 4363,4368 **** --- 4390,4396 ---- || operands[1] == CONST0_RTX (DImode))" { return mips_output_move (operands[0], operands[1]); } [(set_attr "type" "move,const,const,load,store,move,xfer,load,xfer,store,hilo,hilo,hilo,xfer,load,xfer,store") + (set_attr "sb_type" "*,*,*,*,*,*,*,fpload,*,fpstore,*,*,*,*,*,*,*") (set_attr "mode" "DI") (set_attr "length" "4,*,*,*,*,4,4,*,4,*,4,4,4,8,*,8,*")]) *************** dsrl\t%3,%3,1\n\ *** 4488,4493 **** --- 4516,4522 ---- || (GET_CODE (operands[1]) == CONST_INT && INTVAL (operands[1]) == 0))" { return mips_output_move (operands[0], operands[1]); } [(set_attr "type" "move,const,const,load,store,move,xfer,load,xfer,store,xfer,xfer,hilo,hilo,hilo,xfer,load,xfer,store") + (set_attr "sb_type" "*,*,*,*,*,*,*,fpload,*,fpstore,*,*,*,*,*,*,*,*,*") (set_attr "mode" "SI") (set_attr "length" "4,*,*,*,*,4,4,*,4,*,4,4,4,4,4,4,*,4,*")]) *************** dsrl\t%3,%3,1\n\ *** 4606,4611 **** --- 4635,4641 ---- "ISA_HAS_8CC && TARGET_HARD_FLOAT" { return mips_output_move (operands[0], operands[1]); } [(set_attr "type" "move,move,load,store,xfer,xfer,move,load,store") + (set_attr "sb_type" "*,*,*,*,*,*,*,fpload,fpstore") (set_attr "mode" "SI") (set_attr "length" "8,4,*,*,4,4,4,*,*")]) *************** dsrl\t%3,%3,1\n\ *** 4663,4668 **** --- 4693,4699 ---- "ISA_HAS_FP4 && TARGET_HARD_FLOAT" "lwxc1\t%0,%1(%2)" [(set_attr "type" "load") + (set_attr "sb_type" "fpidxload") (set_attr "mode" "SF") (set_attr "length" "4")]) *************** dsrl\t%3,%3,1\n\ *** 4673,4678 **** --- 4704,4710 ---- "ISA_HAS_FP4 && TARGET_HARD_FLOAT" "lwxc1\t%0,%1(%2)" [(set_attr "type" "load") + (set_attr "sb_type" "fpidxload") (set_attr "mode" "SF") (set_attr "length" "4")]) *************** dsrl\t%3,%3,1\n\ *** 4683,4688 **** --- 4715,4721 ---- "ISA_HAS_FP4 && TARGET_HARD_FLOAT && TARGET_DOUBLE_FLOAT" "ldxc1\t%0,%1(%2)" [(set_attr "type" "load") + (set_attr "sb_type" "fpidxload") (set_attr "mode" "DF") (set_attr "length" "4")]) *************** dsrl\t%3,%3,1\n\ *** 4693,4698 **** --- 4726,4732 ---- "ISA_HAS_FP4 && TARGET_HARD_FLOAT && TARGET_DOUBLE_FLOAT" "ldxc1\t%0,%1(%2)" [(set_attr "type" "load") + (set_attr "sb_type" "fpidxload") (set_attr "mode" "DF") (set_attr "length" "4")]) *************** dsrl\t%3,%3,1\n\ *** 4703,4708 **** --- 4737,4743 ---- "ISA_HAS_FP4 && TARGET_HARD_FLOAT" "swxc1\t%0,%1(%2)" [(set_attr "type" "store") + (set_attr "sb_type" "fpidxstore") (set_attr "mode" "SF") (set_attr "length" "4")]) *************** dsrl\t%3,%3,1\n\ *** 4713,4718 **** --- 4748,4754 ---- "ISA_HAS_FP4 && TARGET_HARD_FLOAT" "swxc1\t%0,%1(%2)" [(set_attr "type" "store") + (set_attr "sb_type" "fpidxstore") (set_attr "mode" "SF") (set_attr "length" "4")]) *************** dsrl\t%3,%3,1\n\ *** 4723,4728 **** --- 4759,4765 ---- "ISA_HAS_FP4 && TARGET_HARD_FLOAT && TARGET_DOUBLE_FLOAT" "sdxc1\t%0,%1(%2)" [(set_attr "type" "store") + (set_attr "sb_type" "fpidxstore") (set_attr "mode" "DF") (set_attr "length" "4")]) *************** dsrl\t%3,%3,1\n\ *** 4733,4738 **** --- 4770,4776 ---- "ISA_HAS_FP4 && TARGET_HARD_FLOAT && TARGET_DOUBLE_FLOAT" "sdxc1\t%0,%1(%2)" [(set_attr "type" "store") + (set_attr "sb_type" "fpidxstore") (set_attr "mode" "DF") (set_attr "length" "4")]) *************** dsrl\t%3,%3,1\n\ *** 4972,4977 **** --- 5010,5016 ---- || nonmemory_operand (operands[1], SFmode))" { return mips_output_move (operands[0], operands[1]); } [(set_attr "type" "move,xfer,load,store,xfer,xfer,move,load,store") + (set_attr "sb_type" "*,*,fpload,fpstore,*,*,*,*,*") (set_attr "mode" "SF") (set_attr "length" "4,4,*,*,4,4,4,*,*")]) *************** dsrl\t%3,%3,1\n\ *** 5019,5024 **** --- 5058,5064 ---- || nonmemory_operand (operands[1], DFmode))" { return mips_output_move (operands[0], operands[1]); } [(set_attr "type" "move,xfer,load,store,xfer,xfer,move,load,store") + (set_attr "sb_type" "*,*,fpload,fpstore,*,*,*,*,*") (set_attr "mode" "DF") (set_attr "length" "4,4,*,*,4,4,4,*,*")]) *************** dsrl\t%3,%3,1\n\ *** 5030,5035 **** --- 5070,5076 ---- || nonmemory_operand (operands[1], DFmode))" { return mips_output_move (operands[0], operands[1]); } [(set_attr "type" "move,xfer,load,store,xfer,xfer,move,load,store") + (set_attr "sb_type" "*,*,fpload,fpstore,*,*,*,*,*") (set_attr "mode" "DF") (set_attr "length" "4,8,*,*,8,8,8,*,*")]) *************** dsrl\t%3,%3,1\n\ *** 5123,5128 **** --- 5164,5170 ---- return mips_output_move (operands[0], operands[1]); } [(set_attr "type" "xfer,store") + (set_attr "sb_type" "*,fpstore") (set_attr "mode" "SF") (set_attr "length" "4")]) *************** dsrl\t%3,%3,1\n\ *** 5240,5245 **** --- 5282,5288 ---- return "sll\t%0,%1,%2"; } [(set_attr "type" "arith") + (set_attr "sb_type" "shift") (set_attr "mode" "SI")]) (define_insn "ashlsi3_internal1_extend" *************** dsrl\t%3,%3,1\n\ *** 5254,5259 **** --- 5297,5303 ---- return "sll\t%0,%1,%2"; } [(set_attr "type" "arith") + (set_attr "sb_type" "shift") (set_attr "mode" "DI")]) *************** dsrl\t%3,%3,1\n\ *** 5272,5277 **** --- 5316,5322 ---- return "sll\t%0,%1,%2"; } [(set_attr "type" "arith") + (set_attr "sb_type" "shift") (set_attr "mode" "SI") (set_attr_alternative "length" [(const_int 4) *************** sll\t%L0,%L1,%2\n\ *** 5512,5517 **** --- 5557,5563 ---- return "dsll\t%0,%1,%2"; } [(set_attr "type" "arith") + (set_attr "sb_type" "shift") (set_attr "mode" "DI")]) (define_insn "" *************** sll\t%L0,%L1,%2\n\ *** 5529,5534 **** --- 5575,5581 ---- return "dsll\t%0,%1,%2"; } [(set_attr "type" "arith") + (set_attr "sb_type" "shift") (set_attr "mode" "DI") (set_attr_alternative "length" [(const_int 4) *************** sll\t%L0,%L1,%2\n\ *** 5590,5595 **** --- 5637,5643 ---- return "sra\t%0,%1,%2"; } [(set_attr "type" "arith") + (set_attr "sb_type" "shift") (set_attr "mode" "SI")]) (define_insn "ashrsi3_internal2" *************** sll\t%L0,%L1,%2\n\ *** 5607,5612 **** --- 5655,5661 ---- return "sra\t%0,%1,%2"; } [(set_attr "type" "arith") + (set_attr "sb_type" "shift") (set_attr "mode" "SI") (set_attr_alternative "length" [(const_int 4) *************** sra\t%M0,%M1,%2\n\ *** 5704,5709 **** --- 5753,5759 ---- return "sra\t%L0,%M1,%2\;sra\t%M0,%M1,31"; } [(set_attr "type" "darith") + (set_attr "sb_type" "shift") (set_attr "mode" "DI") (set_attr "length" "8")]) *************** sra\t%M0,%M1,%2\n\ *** 5843,5848 **** --- 5893,5899 ---- return "dsra\t%0,%1,%2"; } [(set_attr "type" "arith") + (set_attr "sb_type" "shift") (set_attr "mode" "DI")]) (define_insn "" *************** sra\t%M0,%M1,%2\n\ *** 5857,5862 **** --- 5908,5914 ---- return "dsra\t%0,%2"; } [(set_attr "type" "arith") + (set_attr "sb_type" "shift") (set_attr "mode" "DI") (set_attr_alternative "length" [(const_int 4) *************** sra\t%M0,%M1,%2\n\ *** 5917,5922 **** --- 5969,5975 ---- return "srl\t%0,%1,%2"; } [(set_attr "type" "arith") + (set_attr "sb_type" "shift") (set_attr "mode" "SI")]) (define_insn "lshrsi3_internal2" *************** sra\t%M0,%M1,%2\n\ *** 5934,5939 **** --- 5987,5993 ---- return "srl\t%0,%1,%2"; } [(set_attr "type" "arith") + (set_attr "sb_type" "shift") (set_attr "mode" "SI") (set_attr_alternative "length" [(const_int 4) *************** srl\t%M0,%M1,%2\n\ *** 6194,6199 **** --- 6248,6254 ---- return "dsrl\t%0,%1,%2"; } [(set_attr "type" "arith") + (set_attr "sb_type" "shift") (set_attr "mode" "DI")]) (define_insn "" *************** srl\t%M0,%M1,%2\n\ *** 6208,6213 **** --- 6263,6269 ---- return "dsrl\t%0,%2"; } [(set_attr "type" "arith") + (set_attr "sb_type" "shift") (set_attr "mode" "DI") (set_attr_alternative "length" [(const_int 4) *************** srl\t%M0,%M1,%2\n\ *** 6231,6236 **** --- 6287,6293 ---- return "ror\t%0,%1,%2"; } [(set_attr "type" "arith") + (set_attr "sb_type" "shift") (set_attr "mode" "SI")]) (define_insn "rotrdi3" *************** srl\t%M0,%M1,%2\n\ *** 6255,6260 **** --- 6312,6318 ---- return "dror\t%0,%1,%2"; } [(set_attr "type" "arith") + (set_attr "sb_type" "shift") (set_attr "mode" "DI")]) *************** srl\t%M0,%M1,%2\n\ *** 6892,6897 **** --- 6950,6956 ---- "!TARGET_MIPS16" "sltu\t%0,%1,1" [(set_attr "type" "arith") + (set_attr "sb_type" "slt") (set_attr "mode" "SI")]) (define_insn "" *************** srl\t%M0,%M1,%2\n\ *** 6901,6906 **** --- 6960,6966 ---- "TARGET_MIPS16" "sltu\t%1,1" [(set_attr "type" "arith") + (set_attr "sb_type" "slt") (set_attr "mode" "SI")]) (define_insn "seq_di_zero" *************** srl\t%M0,%M1,%2\n\ *** 6910,6915 **** --- 6970,6976 ---- "TARGET_64BIT && !TARGET_MIPS16" "sltu\t%0,%1,1" [(set_attr "type" "arith") + (set_attr "sb_type" "slt") (set_attr "mode" "DI")]) (define_insn "" *************** srl\t%M0,%M1,%2\n\ *** 6919,6924 **** --- 6980,6986 ---- "TARGET_64BIT && TARGET_MIPS16" "sltu\t%1,1" [(set_attr "type" "arith") + (set_attr "sb_type" "slt") (set_attr "mode" "DI")]) (define_insn "seq_si" *************** srl\t%M0,%M1,%2\n\ *** 6930,6935 **** --- 6992,6998 ---- xor\t%0,%1,%2\;sltu\t%0,%0,1 xori\t%0,%1,%2\;sltu\t%0,%0,1" [(set_attr "type" "arith") + (set_attr "sb_type" "slt") (set_attr "mode" "SI") (set_attr "length" "8")]) *************** srl\t%M0,%M1,%2\n\ *** 6956,6961 **** --- 7019,7025 ---- xor\t%0,%1,%2\;sltu\t%0,%0,1 xori\t%0,%1,%2\;sltu\t%0,%0,1" [(set_attr "type" "arith") + (set_attr "sb_type" "slt") (set_attr "mode" "DI") (set_attr "length" "8")]) *************** srl\t%M0,%M1,%2\n\ *** 7008,7013 **** --- 7072,7078 ---- "!TARGET_MIPS16" "sltu\t%0,%.,%1" [(set_attr "type" "arith") + (set_attr "sb_type" "slt") (set_attr "mode" "SI")]) (define_insn "sne_di_zero" *************** srl\t%M0,%M1,%2\n\ *** 7017,7022 **** --- 7082,7088 ---- "TARGET_64BIT && !TARGET_MIPS16" "sltu\t%0,%.,%1" [(set_attr "type" "arith") + (set_attr "sb_type" "slt") (set_attr "mode" "DI")]) (define_insn "sne_si" *************** srl\t%M0,%M1,%2\n\ *** 7028,7033 **** --- 7094,7100 ---- xor\t%0,%1,%2\;sltu\t%0,%.,%0 xori\t%0,%1,%x2\;sltu\t%0,%.,%0" [(set_attr "type" "arith") + (set_attr "sb_type" "slt") (set_attr "mode" "SI") (set_attr "length" "8")]) *************** srl\t%M0,%M1,%2\n\ *** 7054,7059 **** --- 7121,7127 ---- xor\t%0,%1,%2\;sltu\t%0,%.,%0 xori\t%0,%1,%x2\;sltu\t%0,%.,%0" [(set_attr "type" "arith") + (set_attr "sb_type" "slt") (set_attr "mode" "DI") (set_attr "length" "8")]) *************** srl\t%M0,%M1,%2\n\ *** 7104,7109 **** --- 7172,7178 ---- "!TARGET_MIPS16" "slt\t%0,%z2,%1" [(set_attr "type" "arith") + (set_attr "sb_type" "slt") (set_attr "mode" "SI")]) (define_insn "" *************** srl\t%M0,%M1,%2\n\ *** 7113,7118 **** --- 7182,7188 ---- "TARGET_MIPS16" "slt\t%2,%1" [(set_attr "type" "arith") + (set_attr "sb_type" "slt") (set_attr "mode" "SI")]) (define_insn "sgt_di" *************** srl\t%M0,%M1,%2\n\ *** 7122,7127 **** --- 7192,7198 ---- "TARGET_64BIT && !TARGET_MIPS16" "slt\t%0,%z2,%1" [(set_attr "type" "arith") + (set_attr "sb_type" "slt") (set_attr "mode" "DI")]) (define_insn "" *************** srl\t%M0,%M1,%2\n\ *** 7131,7136 **** --- 7202,7208 ---- "TARGET_64BIT && TARGET_MIPS16" "slt\t%2,%1" [(set_attr "type" "arith") + (set_attr "sb_type" "slt") (set_attr "mode" "DI")]) (define_expand "sge" *************** srl\t%M0,%M1,%2\n\ *** 7162,7167 **** --- 7234,7240 ---- "TARGET_DEBUG_C_MODE && !TARGET_MIPS16" "slt\t%0,%1,%2\;xori\t%0,%0,0x0001" [(set_attr "type" "arith") + (set_attr "sb_type" "slt") (set_attr "mode" "SI") (set_attr "length" "8")]) *************** srl\t%M0,%M1,%2\n\ *** 7185,7190 **** --- 7258,7264 ---- "TARGET_64BIT && TARGET_DEBUG_C_MODE && !TARGET_MIPS16" "slt\t%0,%1,%2\;xori\t%0,%0,0x0001" [(set_attr "type" "arith") + (set_attr "sb_type" "slt") (set_attr "mode" "DI") (set_attr "length" "8")]) *************** srl\t%M0,%M1,%2\n\ *** 7231,7236 **** --- 7305,7311 ---- "!TARGET_MIPS16" "slt\t%0,%1,%2" [(set_attr "type" "arith") + (set_attr "sb_type" "slt") (set_attr "mode" "SI")]) (define_insn "" *************** srl\t%M0,%M1,%2\n\ *** 7240,7245 **** --- 7315,7321 ---- "TARGET_MIPS16" "slt\t%1,%2" [(set_attr "type" "arith") + (set_attr "sb_type" "slt") (set_attr "mode" "SI") (set_attr_alternative "length" [(const_int 4) *************** srl\t%M0,%M1,%2\n\ *** 7254,7259 **** --- 7330,7336 ---- "TARGET_64BIT && !TARGET_MIPS16" "slt\t%0,%1,%2" [(set_attr "type" "arith") + (set_attr "sb_type" "slt") (set_attr "mode" "DI")]) (define_insn "" *************** srl\t%M0,%M1,%2\n\ *** 7263,7268 **** --- 7340,7346 ---- "TARGET_64BIT && TARGET_MIPS16" "slt\t%1,%2" [(set_attr "type" "arith") + (set_attr "sb_type" "slt") (set_attr "mode" "DI") (set_attr_alternative "length" [(const_int 4) *************** srl\t%M0,%M1,%2\n\ *** 7305,7310 **** --- 7383,7389 ---- return "slt\t%0,%1,%2"; } [(set_attr "type" "arith") + (set_attr "sb_type" "slt") (set_attr "mode" "SI")]) (define_insn "" *************** srl\t%M0,%M1,%2\n\ *** 7317,7322 **** --- 7396,7402 ---- return "slt\t%1,%2"; } [(set_attr "type" "arith") + (set_attr "sb_type" "slt") (set_attr "mode" "SI") (set (attr "length") (if_then_else (match_operand:VOID 2 "m16_uimm8_m1_1" "") (const_int 4) *************** srl\t%M0,%M1,%2\n\ *** 7332,7337 **** --- 7412,7418 ---- return "slt\t%0,%1,%2"; } [(set_attr "type" "arith") + (set_attr "sb_type" "slt") (set_attr "mode" "DI")]) (define_insn "" *************** srl\t%M0,%M1,%2\n\ *** 7344,7349 **** --- 7425,7431 ---- return "slt\t%1,%2"; } [(set_attr "type" "arith") + (set_attr "sb_type" "slt") (set_attr "mode" "DI") (set (attr "length") (if_then_else (match_operand:VOID 2 "m16_uimm8_m1_1" "") (const_int 4) *************** srl\t%M0,%M1,%2\n\ *** 7356,7361 **** --- 7438,7444 ---- "TARGET_DEBUG_C_MODE && !TARGET_MIPS16" "slt\t%0,%z2,%1\;xori\t%0,%0,0x0001" [(set_attr "type" "arith") + (set_attr "sb_type" "slt") (set_attr "mode" "SI") (set_attr "length" "8")]) *************** srl\t%M0,%M1,%2\n\ *** 7379,7384 **** --- 7462,7468 ---- "TARGET_64BIT && TARGET_DEBUG_C_MODE && !TARGET_MIPS16" "slt\t%0,%z2,%1\;xori\t%0,%0,0x0001" [(set_attr "type" "arith") + (set_attr "sb_type" "slt") (set_attr "mode" "DI") (set_attr "length" "8")]) *************** srl\t%M0,%M1,%2\n\ *** 7428,7433 **** --- 7512,7518 ---- "!TARGET_MIPS16" "sltu\t%0,%z2,%1" [(set_attr "type" "arith") + (set_attr "sb_type" "slt") (set_attr "mode" "SI")]) (define_insn "" *************** srl\t%M0,%M1,%2\n\ *** 7437,7442 **** --- 7522,7528 ---- "TARGET_MIPS16" "sltu\t%2,%1" [(set_attr "type" "arith") + (set_attr "sb_type" "slt") (set_attr "mode" "SI")]) (define_insn "sgtu_di" *************** srl\t%M0,%M1,%2\n\ *** 7446,7451 **** --- 7532,7538 ---- "TARGET_64BIT && !TARGET_MIPS16" "sltu\t%0,%z2,%1" [(set_attr "type" "arith") + (set_attr "sb_type" "slt") (set_attr "mode" "DI")]) (define_insn "" *************** srl\t%M0,%M1,%2\n\ *** 7455,7460 **** --- 7542,7548 ---- "TARGET_64BIT && TARGET_MIPS16" "sltu\t%2,%1" [(set_attr "type" "arith") + (set_attr "sb_type" "slt") (set_attr "mode" "DI")]) (define_expand "sgeu" *************** srl\t%M0,%M1,%2\n\ *** 7509,7514 **** --- 7597,7603 ---- "TARGET_64BIT && TARGET_DEBUG_C_MODE && !TARGET_MIPS16" "sltu\t%0,%1,%2\;xori\t%0,%0,0x0001" [(set_attr "type" "arith") + (set_attr "sb_type" "slt") (set_attr "mode" "DI") (set_attr "length" "8")]) *************** srl\t%M0,%M1,%2\n\ *** 7555,7560 **** --- 7644,7650 ---- "!TARGET_MIPS16" "sltu\t%0,%1,%2" [(set_attr "type" "arith") + (set_attr "sb_type" "slt") (set_attr "mode" "SI")]) (define_insn "" *************** srl\t%M0,%M1,%2\n\ *** 7564,7569 **** --- 7654,7660 ---- "TARGET_MIPS16" "sltu\t%1,%2" [(set_attr "type" "arith") + (set_attr "sb_type" "slt") (set_attr "mode" "SI") (set_attr_alternative "length" [(const_int 4) *************** srl\t%M0,%M1,%2\n\ *** 7578,7583 **** --- 7669,7675 ---- "TARGET_64BIT && !TARGET_MIPS16" "sltu\t%0,%1,%2" [(set_attr "type" "arith") + (set_attr "sb_type" "slt") (set_attr "mode" "DI")]) (define_insn "" *************** srl\t%M0,%M1,%2\n\ *** 7587,7592 **** --- 7679,7685 ---- "TARGET_64BIT && TARGET_MIPS16" "sltu\t%1,%2" [(set_attr "type" "arith") + (set_attr "sb_type" "slt") (set_attr "mode" "DI") (set_attr_alternative "length" [(const_int 4) *************** srl\t%M0,%M1,%2\n\ *** 7629,7634 **** --- 7722,7728 ---- return "sltu\t%0,%1,%2"; } [(set_attr "type" "arith") + (set_attr "sb_type" "slt") (set_attr "mode" "SI")]) (define_insn "" *************** srl\t%M0,%M1,%2\n\ *** 7641,7646 **** --- 7735,7741 ---- return "sltu\t%1,%2"; } [(set_attr "type" "arith") + (set_attr "sb_type" "slt") (set_attr "mode" "SI") (set (attr "length") (if_then_else (match_operand:VOID 2 "m16_uimm8_m1_1" "") (const_int 4) *************** srl\t%M0,%M1,%2\n\ *** 7656,7661 **** --- 7751,7757 ---- return "sltu\t%0,%1,%2"; } [(set_attr "type" "arith") + (set_attr "sb_type" "slt") (set_attr "mode" "DI")]) (define_insn "" *************** srl\t%M0,%M1,%2\n\ *** 7668,7673 **** --- 7764,7770 ---- return "sltu\t%1,%2"; } [(set_attr "type" "arith") + (set_attr "sb_type" "slt") (set_attr "mode" "DI") (set (attr "length") (if_then_else (match_operand:VOID 2 "m16_uimm8_m1_1" "") (const_int 4) *************** srl\t%M0,%M1,%2\n\ *** 7680,7685 **** --- 7777,7783 ---- "TARGET_DEBUG_C_MODE && !TARGET_MIPS16" "sltu\t%0,%z2,%1\;xori\t%0,%0,0x0001" [(set_attr "type" "arith") + (set_attr "sb_type" "slt") (set_attr "mode" "SI") (set_attr "length" "8")]) *************** srl\t%M0,%M1,%2\n\ *** 7703,7708 **** --- 7801,7807 ---- "TARGET_64BIT && TARGET_DEBUG_C_MODE && !TARGET_MIPS16" "sltu\t%0,%z2,%1\;xori\t%0,%0,0x0001" [(set_attr "type" "arith") + (set_attr "sb_type" "slt") (set_attr "mode" "DI") (set_attr "length" "8")]) Index: sb1.md =================================================================== RCS file: sb1.md diff -N sb1.md *** /dev/null 1 Jan 1970 00:00:00 -0000 --- sb1.md 27 Feb 2004 03:16:08 -0000 *************** *** 0 **** --- 1,535 ---- + ;; + ;; DFA-based pipeline description for Broadcom SB-1 + ;; + + ;; The Broadcom SB-1 core is 4-way superscalar, in-order. It has 2 load/store + ;; pipes (one of which can support some ALU operations), 2 alu pipes, 2 FP + ;; pipes, and 1 MDMX pipes. It can issue 2 ls insns and 2 exe/fpu/mdmx insns + ;; each cycle. + + ;; We model the 4-way issue by ordering unit choices. The possible choices are + ;; {ex1,fp1}|{ex0,fp0}|ls1|ls0. Instructions issue to the first eligible unit + ;; in the list in most cases. Non-indexed load/stores issue to ls0 first. + ;; simple alu operations issue to ls1 if it is still available, and their + ;; operands are ready (no co-issue with loads), otherwise to the first + ;; available ex unit. + + ;; When exceptions are enabled, can only issue FP insns to fp1. This is + ;; to ensure that instructions complete in order. We should perhaps assume + ;; that exceptions are always enabled, and hence only fp1 is usable. Ask + ;; customer for clarification. + + ;; In 32-bit mode, dependent FP can't co-issue with load, and only one FP exe + ;; insn can issue per cycle (fp1). + + ;; The A1 MDMX pipe is separate from the FP pipes, but uses the same register + ;; file. As a result, once an MDMX insn is issued, no FP insns can be issued + ;; for 3 cycles. When an FP insn is issued, no MDMX insn can be issued for + ;; 5 cycles. This is currently not handled because there is no MDMX insn + ;; support as yet. + + ;; + ;; Use one automata to start. + ;; + (define_automaton "sb1_cpu, sb1_cpu_div") + + ;; Load/store function units. + (define_cpu_unit "sb1_ls0" "sb1_cpu") + (define_cpu_unit "sb1_ls1" "sb1_cpu") + + ;; CPU function units. + (define_cpu_unit "sb1_ex0" "sb1_cpu") + (define_cpu_unit "sb1_ex1" "sb1_cpu") + + ;; The divide unit is not pipelined, and blocks hi/lo reads and writes. + (define_cpu_unit "sb1_div" "sb1_cpu_div") + ;; DMULT block any multiply from issuing in the next cycle. + (define_cpu_unit "sb1_mul" "sb1_cpu") + + ;; Floating-point units. + (define_cpu_unit "sb1_fp0" "sb1_cpu") + (define_cpu_unit "sb1_fp1" "sb1_cpu") + + ;; Can only issue to one of the ex and fp pipes at a time. + (exclusion_set "sb1_ex0" "sb1_fp0") + (exclusion_set "sb1_ex1" "sb1_fp1") + + ;; Define reservations for common combinations. + + ;; For long cycle operations, the FPU has a 4 cycle pipeline that repeats, + ;; effectively re-issuing the operation every 4 cycles. This means that we + ;; can have at most 4 long-cycle operations per pipe. + + ;; ??? The fdiv operations should be e.g. + ;; sb1_fp1_4cycles*7" | "sb1_fp0_4cycle*7 + ;; but the DFA is too large when we do that. Perhaps have to use scheduler + ;; hooks here. + + ;; ??? Try limiting scheduler to 2 long latency operations, and see if this + ;; results in a usable DFA, and whether it helps code performance. + + ;;(define_reservation "sb1_fp0_4cycles" "sb1_fp0, nothing*3") + ;;(define_reservation "sb1_fp1_4cycles" "sb1_fp1, nothing*3") + + ;; + ;; The ordering of the instruction-execution-path/resource-usage + ;; descriptions (also known as reservation RTL) is roughly ordered + ;; based on the define attribute RTL for the "type" classification. + ;; When modifying, remember that the first test that matches is the + ;; reservation used! + ;; + + (define_insn_reservation "ir_sb1_unknown" 1 + (and (eq_attr "cpu" "sb1") + (eq_attr "type" "unknown,multi")) + "sb1_ls0+sb1_ls1+sb1_ex0+sb1_ex1+sb1_fp0+sb1_fp1") + + ;; predicted taken branch causes 2 cycle ifetch bubble. predicted not + ;; taken branch causes 0 cycle ifetch bubble. mispredicted branch causes 8 + ;; cycle ifetch bubble. We assume all branches predicated not taken. + + (define_insn_reservation "ir_sb1_branch" 0 + (and (eq_attr "cpu" "sb1") + (eq_attr "type" "branch,jump,call")) + "sb1_ex0") + + ;; ??? This is 1 cycle for ldl/ldr to ldl/ldr when they use the same data + ;; register as destination. + + ;; ??? Can co-issue a load with a dependent arith insn if it executes on an EX + ;; unit. Can not co-issue if the dependent insn executes on an LS unit. + + ;; A load normally has a latency of zero cycles. In some cases, dependent + ;; insns can be issued in the same cycle. However, a value of 1 gives + ;; better performance in empirical testing. + + (define_insn_reservation "ir_sb1_load" 1 + (and (eq_attr "cpu" "sb1") + (and (eq_attr "type" "load,prefetch") + (eq_attr "sb_type" "!fpidxload,fpload"))) + "sb1_ls0 | sb1_ls1") + + ;; Can not co-issue fpload with fp exe when in 32-bit mode. + + (define_insn_reservation "ir_sb1_fpload" 0 + (and (eq_attr "cpu" "sb1") + (and (eq_attr "sb_type" "fpload") + (ne (symbol_ref "TARGET_FLOAT64") + (const_int 0)))) + "sb1_ls0 | sb1_ls1") + + (define_insn_reservation "ir_sb1_fpload_32bitfp" 1 + (and (eq_attr "cpu" "sb1") + (and (eq_attr "sb_type" "fpload") + (eq (symbol_ref "TARGET_FLOAT64") + (const_int 0)))) + "sb1_ls0 | sb1_ls1") + + ;; Indexed loads can only execute on LS1 pipe. + + (define_insn_reservation "ir_sb1_fpidxload" 0 + (and (eq_attr "cpu" "sb1") + (and (eq_attr "sb_type" "fpidxload") + (ne (symbol_ref "TARGET_FLOAT64") + (const_int 0)))) + "sb1_ls1") + + (define_insn_reservation "ir_sb1_fpidxload_32bitfp" 1 + (and (eq_attr "cpu" "sb1") + (and (eq_attr "sb_type" "fpidxload") + (eq (symbol_ref "TARGET_FLOAT64") + (const_int 0)))) + "sb1_ls1") + + ;; prefx can only execute on the ls1 pipe. + + (define_insn_reservation "ir_sb1_prefetchx" 0 + (and (eq_attr "cpu" "sb1") + (eq_attr "type" "prefetchx")) + "sb1_ls1") + + ;; ??? There is a 4.5 cycle latency if a store is followed by a load, and + ;; there is a RAW dependency. + + (define_insn_reservation "ir_sb1_store" 1 + (and (eq_attr "cpu" "sb1") + (and (eq_attr "type" "store") + (eq_attr "sb_type" "!fpidxstore,fpstore"))) + "sb1_ls0+sb1_ex1 | sb1_ls0+sb1_ex0 | sb1_ls1+sb1_ex1 | sb1_ls1+sb1_ex0") + + (define_insn_reservation "ir_sb1_fpstore" 1 + (and (eq_attr "cpu" "sb1") + (eq_attr "sb_type" "fpstore")) + "sb1_ls0+sb1_fp1 | sb1_ls0+sb1_fp0 | sb1_ls1+sb1_fp1 | sb1_ls1+sb1_fp0") + + ;; Indexed stores can only execute on LS1 pipe. + + (define_insn_reservation "ir_sb1_fpidxstore" 1 + (and (eq_attr "cpu" "sb1") + (eq_attr "sb_type" "fpidxstore")) + "sb1_ls1+sb1_fp1 | sb1_ls1+sb1_fp0") + + ;; Load latencies are 3 cycles for one load to another load or store (address + ;; only). This is 0 cycles for one load to a store using it as the data + ;; written. + + (define_bypass 3 + "ir_sb1_load,ir_sb1_fpload,ir_sb1_fpload_32bitfp,ir_sb1_fpidxload,ir_sb1_fpidxload_32bitfp" + "ir_sb1_load,ir_sb1_fpload,ir_sb1_fpload_32bitfp,ir_sb1_fpidxload,ir_sb1_fpidxload_32bitfp,ir_sb1_prefetchx" + "mips_ld_address_bypass_p") + + (define_bypass 3 + "ir_sb1_load,ir_sb1_fpload,ir_sb1_fpload_32bitfp,ir_sb1_fpidxload,ir_sb1_fpidxload_32bitfp" + "ir_sb1_store,ir_sb1_fpstore,ir_sb1_fpidxstore" + "mips_st_address_bypass_p") + + ;; Simple alu instructions can execute on the LS1 unit. + + ;; ??? A simple alu insn issued on an LS unit has 0 cycle latency to an EX + ;; insn, to a store (for data), and to an xfer insn. It has 1 cycle latency to + ;; another LS insn (excluding store data). A simple alu insn issued on an EX + ;; unit has a latency of 5 cycles when the results goes to a LS unit (exluding + ;; store data), otherwise a latency of 1 cycle. + + ;; ??? We can not handle latencies properly for simple alu instructions + ;; within the DFA pipeline model. Latencies can be defined only from one + ;; insn reservation to another. We can't make them depend on which function + ;; unit was used. This isn't a DFA flaw. There is a conflict here, as we + ;; need to know the latency before we can determine which unit will be + ;; available, but we need to know which unit it is issued to before we can + ;; compute the latency. Perhaps this can be handled via scheduler hooks. + ;; This needs to be investigated. + + ;; ??? Optimal scheduling taking the LS units into account seems to require + ;; a pre-scheduling pass. We need to determine which instructions feed results + ;; into store/load addresses, and thus benefit most from being issued to the + ;; LS unit. Also, we need to prune the list to ensure we don't overschedule + ;; insns to the LS unit, and that we don't conflict with insns that need LS1 + ;; such as indexed loads. We then need to emit nops to ensure that simple + ;; alu instructions that are not supposed to be scheduled to LS1 don't + ;; accidentally end up there because LS1 is free when they are issued. This + ;; will be a lot of work, and it isn't clear how useful it will be. + + ;; Empirical testing shows that 2 gives the best result. + + (define_insn_reservation "ir_sb1_simple_alu" 2 + (and (eq_attr "cpu" "sb1") + (and (eq_attr "type" "move,const,arith,darith") + (eq_attr "sb_type" "!slt,clz,trap,shift,icmp"))) + "sb1_ls1 | sb1_ex1 | sb1_ex0") + + (define_insn_reservation "ir_sb1_alu" 1 + (and (eq_attr "cpu" "sb1") + (eq_attr "type" "condmove,icmp,nop")) + "sb1_ex1 | sb1_ex0") + + ;; These are type arith/darith that are not simple alu. + + (define_insn_reservation "ir_sb1_other_alu" 1 + (and (eq_attr "cpu" "sb1") + (eq_attr "sb_type" "shift,icmp")) + "sb1_ex1 | sb1_ex0") + + ;; These are type arith/darith that only execute on the EX0 unit. + + (define_insn_reservation "ir_sb1_alu_0" 1 + (and (eq_attr "cpu" "sb1") + (eq_attr "sb_type" "slt,clz,trap")) + "sb1_ex0") + + ;; An alu insn issued on an EX unit has a latency of 5 cycles when the + ;; result goes to a LS unit (excluding store data). + + (define_bypass 5 + "ir_sb1_alu,ir_sb1_other_alu,ir_sb1_alu_0,ir_sb1_mfhi,ir_sb1_mflo" + "ir_sb1_load,ir_sb1_fpload,ir_sb1_fpload_32bitfp,ir_sb1_fpidxload,ir_sb1_fpidxload_32bitfp,ir_sb1_prefetchx" + "mips_ld_address_bypass_p") + + (define_bypass 5 + "ir_sb1_alu,ir_sb1_other_alu,ir_sb1_alu_0,ir_sb1_mfhi,ir_sb1_mflo" + "ir_sb1_store,ir_sb1_fpstore,ir_sb1_fpidxstore" + "mips_st_address_bypass_p") + + ;; mf{hi,lo} is 1 cycle. + + (define_insn_reservation "ir_sb1_mfhi" 1 + (and (eq_attr "cpu" "sb1") + (and (eq_attr "type" "hilo") + (and (not (match_operand 0 "hilo_operand" "")) + (not (match_operand 1 "lo_operand" ""))))) + "sb1_ex1") + + (define_insn_reservation "ir_sb1_mflo" 1 + (and (eq_attr "cpu" "sb1") + (and (eq_attr "type" "hilo") + (and (not (match_operand 0 "hilo_operand" "")) + (match_operand 1 "lo_operand" "")))) + "sb1_ex1") + + ;; mt{hi,lo} to mul/div is 4 cycles. + + (define_insn_reservation "ir_sb1_mthilo" 4 + (and (eq_attr "cpu" "sb1") + (and (eq_attr "type" "hilo") + (match_operand 0 "hilo_operand" ""))) + "sb1_ex1") + + ;; mt{hi,lo} to mf{hi,lo} is 3 cycles. + + (define_bypass 3 "ir_sb1_mthilo" "ir_sb1_mfhi,ir_sb1_mflo") + + ;; multiply latency to an EX operation is 3 cycles. + + (define_insn_reservation "ir_sb1_mulsi" 3 + (and (eq_attr "cpu" "sb1") + (and (eq_attr "type" "imul,imadd") + (eq_attr "mode" "SI"))) + "sb1_ex1+sb1_mul") + + ;; muldi to mfhi is 4 cycles. + ;; Blocks any other multiply insn issue for 1 cycle. + + (define_insn_reservation "ir_sb1_muldi" 4 + (and (eq_attr "cpu" "sb1") + (and (eq_attr "type" "imul") + (eq_attr "mode" "DI"))) + "sb1_ex1+sb1_mul, sb1_mul") + + ;; muldi to mflo is 3 cycles. + + (define_bypass 3 "ir_sb1_muldi" "ir_sb1_mflo") + + ;; mul latency is 7 cycles if the result is used by any LS insn. + + (define_bypass 7 + "ir_sb1_mulsi,ir_sb1_muldi" + "ir_sb1_load,ir_sb1_fpload,ir_sb1_fpload_32bitfp,ir_sb1_fpidxload,ir_sb1_fpidxload_32bitfp,ir_sb1_prefetchx" + "mips_ld_address_bypass_p") + + (define_bypass 7 + "ir_sb1_mulsi,ir_sb1_muldi" + "ir_sb1_store,ir_sb1_fpstore,ir_sb1_fpidxstore" + "mips_st_address_bypass_p") + + ;; The divide unit is not pipelined. Divide busy is asserted in the 4th + ;; cycle, and then deasserted on the latency cycle. So only one divide at + ;; a time, but the first/last 4 cycles can overlap. + + ;; ??? All divides block writes to hi/lo regs. hi/lo regs are written 4 cycles + ;; after the latency cycle for divides (e.g. 40/72). dmult writes lo in + ;; cycle 7, and hi in cycle 8. All other insns write hi/lo regs in cycle 7. + ;; Default for output dependencies is the difference in latencies, which is + ;; only 1 cycle off here, e.g. div to mtlo stalls for 32 cycles, but should + ;; stall for 33 cycles. This does not seem significant enough to worry about. + + (define_insn_reservation "ir_sb1_divsi" 36 + (and (eq_attr "cpu" "sb1") + (and (eq_attr "type" "idiv") + (eq_attr "mode" "SI"))) + "sb1_ex1, nothing*3, sb1_div*32") + + (define_insn_reservation "ir_sb1_divdi" 68 + (and (eq_attr "cpu" "sb1") + (and (eq_attr "type" "idiv") + (eq_attr "mode" "DI"))) + "sb1_ex1, nothing*3, sb1_div*64") + + (define_insn_reservation "ir_sb1_fpu_2pipes" 4 + (and (eq_attr "cpu" "sb1") + (and (eq_attr "type" "fadd,fmul,fabs,fneg,fcvt") + (and (ne (symbol_ref "TARGET_FLOAT64") + (const_int 0)) + (eq (symbol_ref "mips_sb1_fp_exceptions") + (const_int 0))))) + "sb1_fp1 | sb1_fp0") + + (define_insn_reservation "ir_sb1_fpu_1pipe" 4 + (and (eq_attr "cpu" "sb1") + (and (eq_attr "type" "fadd,fmul,fabs,fneg,fcvt") + (ior (eq (symbol_ref "TARGET_FLOAT64") + (const_int 0)) + (ne (symbol_ref "mips_sb1_fp_exceptions") + (const_int 0))))) + "sb1_fp1") + + ;; ??? madd/msub 4-cycle latency to itself (same fr?), but 8 cycle latency + ;; otherwise. + + ;; ??? Blocks issue of another non-madd/msub after 4 cycles. + + (define_insn_reservation "ir_sb1_fmadd_2pipes" 8 + (and (eq_attr "cpu" "sb1") + (and (eq_attr "type" "fmadd") + (and (ne (symbol_ref "TARGET_FLOAT64") + (const_int 0)) + (eq (symbol_ref "mips_sb1_fp_exceptions") + (const_int 0))))) + "sb1_fp1 | sb1_fp0") + + (define_insn_reservation "ir_sb1_fmadd_1pipe" 8 + (and (eq_attr "cpu" "sb1") + (and (eq_attr "type" "fmadd") + (ior (eq (symbol_ref "TARGET_FLOAT64") + (const_int 0)) + (ne (symbol_ref "mips_sb1_fp_exceptions") + (const_int 0))))) + "sb1_fp1") + + (define_insn_reservation "ir_sb1_fcmp" 4 + (and (eq_attr "cpu" "sb1") + (eq_attr "type" "fcmp")) + "sb1_fp1") + + ;; mtc1 latency 5 cycles. + + (define_insn_reservation "ir_sb1_mtxfer" 5 + (and (eq_attr "cpu" "sb1") + (and (eq_attr "type" "xfer") + (match_operand 0 "fp_register_operand" ""))) + "sb1_fp0") + + ;; mfc1 latency 1 cycle. + + (define_insn_reservation "ir_sb1_mfxfer" 1 + (and (eq_attr "cpu" "sb1") + (and (eq_attr "type" "xfer") + (not (match_operand 0 "fp_register_operand" "")))) + "sb1_fp0") + + ;; ??? Can deliver at most 1 result per every 6 cycles because of issue + ;; restrictions. + + (define_insn_reservation "ir_sb1_divsf_2pipes" 24 + (and (eq_attr "cpu" "sb1") + (and (eq_attr "type" "fdiv") + (and (eq_attr "mode" "SF") + (and (ne (symbol_ref "TARGET_FLOAT64") + (const_int 0)) + (eq (symbol_ref "mips_sb1_fp_exceptions") + (const_int 0)))))) + "sb1_fp1 | sb1_fp0") + + (define_insn_reservation "ir_sb1_divsf_1pipes" 24 + (and (eq_attr "cpu" "sb1") + (and (eq_attr "type" "fdiv") + (and (eq_attr "mode" "SF") + (ior (eq (symbol_ref "TARGET_FLOAT64") + (const_int 0)) + (ne (symbol_ref "mips_sb1_fp_exceptions") + (const_int 0)))))) + "sb1_fp1") + + ;; ??? Can deliver at most 1 result per every 8 cycles because of issue + ;; restrictions. + + (define_insn_reservation "ir_sb1_divdf_2pipes" 32 + (and (eq_attr "cpu" "sb1") + (and (eq_attr "type" "fdiv") + (and (eq_attr "mode" "SF") + (and (ne (symbol_ref "TARGET_FLOAT64") + (const_int 0)) + (eq (symbol_ref "mips_sb1_fp_exceptions") + (const_int 0)))))) + "sb1_fp1 | sb1_fp0") + + (define_insn_reservation "ir_sb1_divdf_1pipe" 32 + (and (eq_attr "cpu" "sb1") + (and (eq_attr "type" "fdiv") + (and (eq_attr "mode" "SF") + (ior (eq (symbol_ref "TARGET_FLOAT64") + (const_int 0)) + (ne (symbol_ref "mips_sb1_fp_exceptions") + (const_int 0)))))) + "sb1_fp1") + + ;; ??? Can deliver at most 1 result per every 7 cycles because of issue + ;; restrictions. + + (define_insn_reservation "ir_sb1_sqrtsf_2pipes" 28 + (and (eq_attr "cpu" "sb1") + (and (eq_attr "type" "fsqrt") + (and (eq_attr "mode" "SF") + (and (ne (symbol_ref "TARGET_FLOAT64") + (const_int 0)) + (eq (symbol_ref "mips_sb1_fp_exceptions") + (const_int 0)))))) + "sb1_fp1 | sb1_fp0") + + (define_insn_reservation "ir_sb1_sqrtsf_1pipe" 28 + (and (eq_attr "cpu" "sb1") + (and (eq_attr "type" "fsqrt") + (and (eq_attr "mode" "SF") + (ior (eq (symbol_ref "TARGET_FLOAT64") + (const_int 0)) + (ne (symbol_ref "mips_sb1_fp_exceptions") + (const_int 0)))))) + "sb1_fp1") + + ;; ??? Can deliver at most 1 result per every 10 cycles because of issue + ;; restrictions. + + (define_insn_reservation "ir_sb1_sqrtdf_2pipes" 40 + (and (eq_attr "cpu" "sb1") + (and (eq_attr "type" "fsqrt") + (and (eq_attr "mode" "DF") + (and (ne (symbol_ref "TARGET_FLOAT64") + (const_int 0)) + (eq (symbol_ref "mips_sb1_fp_exceptions") + (const_int 0)))))) + "sb1_fp1 | sb1_fp0") + + (define_insn_reservation "ir_sb1_sqrtdf_1pipe" 40 + (and (eq_attr "cpu" "sb1") + (and (eq_attr "type" "fsqrt") + (and (eq_attr "mode" "DF") + (ior (eq (symbol_ref "TARGET_FLOAT64") + (const_int 0)) + (ne (symbol_ref "mips_sb1_fp_exceptions") + (const_int 0)))))) + "sb1_fp1") + + ;; ??? Can deliver at most 1 result per every 4 cycles because of issue + ;; restrictions. + + (define_insn_reservation "ir_sb1_rsqrtsf_2pipes" 16 + (and (eq_attr "cpu" "sb1") + (and (eq_attr "type" "frsqrt") + (and (eq_attr "mode" "SF") + (and (ne (symbol_ref "TARGET_FLOAT64") + (const_int 0)) + (eq (symbol_ref "mips_sb1_fp_exceptions") + (const_int 0)))))) + "sb1_fp1 | sb1_fp0") + + (define_insn_reservation "ir_sb1_rsqrtsf_1pipe" 16 + (and (eq_attr "cpu" "sb1") + (and (eq_attr "type" "frsqrt") + (and (eq_attr "mode" "SF") + (ior (eq (symbol_ref "TARGET_FLOAT64") + (const_int 0)) + (ne (symbol_ref "mips_sb1_fp_exceptions") + (const_int 0)))))) + "sb1_fp1") + + ;; ??? Can deliver at most 1 result per every 7 cycles because of issue + ;; restrictions. + + (define_insn_reservation "ir_sb1_rsqrtdf_2pipes" 28 + (and (eq_attr "cpu" "sb1") + (and (eq_attr "type" "frsqrt") + (and (eq_attr "mode" "DF") + (and (ne (symbol_ref "TARGET_FLOAT64") + (const_int 0)) + (eq (symbol_ref "mips_sb1_fp_exceptions") + (const_int 0)))))) + "sb1_fp1 | sb1_fp0") + + (define_insn_reservation "ir_sb1_rsqrtdf_1pipe" 28 + (and (eq_attr "cpu" "sb1") + (and (eq_attr "type" "frsqrt") + (and (eq_attr "mode" "DF") + (ior (eq (symbol_ref "TARGET_FLOAT64") + (const_int 0)) + (ne (symbol_ref "mips_sb1_fp_exceptions") + (const_int 0)))))) + "sb1_fp1")