From 15b9ea103987d9b7188118cc23170658f1d86d85 Mon Sep 17 00:00:00 2001 From: mkuvyrkov Date: Tue, 6 Nov 2007 16:52:17 +0000 Subject: [PATCH] * config/m68k/m68k.c (sched-int.h, insn-codes.h): New includes. (TARGET_SCHED_ADJUST_COST, TARGET_SCHED_VARIABLE_ISSUE, TARGET_SCHED_INIT_GLOBAL, TARGET_SCHED_FINISH_GLOBAL, TARGET_SCHED_INIT, TARGET_SCHED_DFA_PRE_ADVANCE_CYCLE, TARGET_SCHED_DFA_POST_ADVANCE_CYCLE): Redefine. (m68k_sched_attr_type2): New function. (sched_adjust_cost_state): New static variable. (m68k_sched_adjust_cost): New static function implementing scheduler hook. (sched_ib_size, sched_ib_filled, sched_ib_insn, sched_mem_unit_code): New static variables. (m68k_sched_variable_issue): New static function implementing scheduler hook. (sched_dump_class_def, sched_dump_class_func_t): New typedefs. (sched_dump_split_class): New static function. (sched_dump_dfa_guess_unit_code, sched_dump_dfa_state): New static variables. (sched_dump_dfa_class, m68k_sched_dump): New static function. (m68k_sched_md_init_global, m68k_sched_md_finish_global, m68k_sched_md_init, m68k_sched_dfa_pre_advance_cycle, m68k_sched_dfa_post_advance_cycle): New static functions implementing scheduler hooks. * config/m68k/m68k.h (m68k_sched_attr_type2): Declare. (CPU_UNITS_QUERY): Define. * config/m68k/cf.md: New file. * config/m68k/m68.md (cf.md): New include. git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@129938 138bc75d-0d04-0410-961f-82ee72b054a4 --- gcc/ChangeLog | 31 ++ gcc/config/m68k/cf.md | 679 ++++++++++++++++++++++++++++++++++++++++++ gcc/config/m68k/m68k-protos.h | 1 + gcc/config/m68k/m68k.c | 480 +++++++++++++++++++++++++++++ gcc/config/m68k/m68k.h | 1 + gcc/config/m68k/m68k.md | 2 + 6 files changed, 1194 insertions(+) create mode 100644 gcc/config/m68k/cf.md diff --git a/gcc/ChangeLog b/gcc/ChangeLog index 0025efaa506..96f7129af90 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,34 @@ +2007-11-06 Maxim Kuvyrkov + + * config/m68k/m68k.c (sched-int.h, insn-codes.h): New includes. + (TARGET_SCHED_ADJUST_COST, TARGET_SCHED_VARIABLE_ISSUE, + TARGET_SCHED_INIT_GLOBAL, TARGET_SCHED_FINISH_GLOBAL, + TARGET_SCHED_INIT, TARGET_SCHED_DFA_PRE_ADVANCE_CYCLE, + TARGET_SCHED_DFA_POST_ADVANCE_CYCLE): Redefine. + (m68k_sched_attr_type2): New function. + (sched_adjust_cost_state): New static variable. + (m68k_sched_adjust_cost): New static function implementing + scheduler hook. + (sched_ib_size, sched_ib_filled, sched_ib_insn, sched_mem_unit_code): + New static variables. + (m68k_sched_variable_issue): New static function implementing + scheduler hook. + (sched_dump_class_def, sched_dump_class_func_t): New typedefs. + (sched_dump_split_class): New static function. + (sched_dump_dfa_guess_unit_code, sched_dump_dfa_state): New static + variables. + (sched_dump_dfa_class, m68k_sched_dump): New static function. + (m68k_sched_md_init_global, m68k_sched_md_finish_global, + m68k_sched_md_init, m68k_sched_dfa_pre_advance_cycle, + m68k_sched_dfa_post_advance_cycle): New static functions implementing + scheduler hooks. + + * config/m68k/m68k.h (m68k_sched_attr_type2): Declare. + (CPU_UNITS_QUERY): Define. + + * config/m68k/cf.md: New file. + * config/m68k/m68.md (cf.md): New include. + 2007-11-06 Tom Tromey PR c++/32256, PR c++/32368: diff --git a/gcc/config/m68k/cf.md b/gcc/config/m68k/cf.md new file mode 100644 index 00000000000..b9c135c9901 --- /dev/null +++ b/gcc/config/m68k/cf.md @@ -0,0 +1,679 @@ +;; ColdFire V2 DFA description. +;; Copyright (C) 2007 Free Software Foundation, Inc. +;; Contributed by CodeSourcery Inc. +;; +;; This file is part of GCC. +;; +;; GCC is free software; you can redistribute it and/or modify +;; it under the terms of the GNU General Public License as published by +;; the Free Software Foundation; either version 2, or (at your option) +;; any later version. +;; +;; GCC is distributed in the hope that it will be useful, +;; but WITHOUT ANY WARRANTY; without even the implied warranty of +;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +;; GNU General Public License for more details. +;; +;; You should have received a copy of the GNU General Public License +;; along with GCC; see the file COPYING. If not, write to +;; the Free Software Foundation, 51 Franklin Street, Fifth Floor, +;; Boston, MA 02110-1301, USA. + +;; ??? To let genattrtab live, implement this attribute in C. +(define_attr "type2" + "alu, alu_l, bcc, bra, call, jmp, lea, move, move_l, mul, pea, rts, unlk, + unknown" + (symbol_ref "m68k_sched_attr_type2 (insn)")) + +;; Instruction Buffer +(define_automaton "cf_v2_ib") + +;; If one of these cpu units is occupied, that means that corresponding +;; word in the buffer is empty. +(define_cpu_unit "cf_v2_ib_w0, cf_v2_ib_w1, cf_v2_ib_w2, cf_v2_ib_w3, cf_v2_ib_w4, cf_v2_ib_w5" "cf_v2_ib") + +(final_presence_set "cf_v2_ib_w1, cf_v2_ib_w2, cf_v2_ib_w3, cf_v2_ib_w4, cf_v2_ib_w5" "cf_v2_ib_w0") +(final_presence_set "cf_v2_ib_w2, cf_v2_ib_w3, cf_v2_ib_w4, cf_v2_ib_w5" "cf_v2_ib_w1") +(final_presence_set "cf_v2_ib_w3, cf_v2_ib_w4, cf_v2_ib_w5" "cf_v2_ib_w2") +(final_presence_set "cf_v2_ib_w4, cf_v2_ib_w5" "cf_v2_ib_w3") +(final_presence_set "cf_v2_ib_w5" "cf_v2_ib_w4") + +;; Occupy 1 word. +(define_reservation "cf_v2_ib1" "cf_v2_ib_w0|cf_v2_ib_w1|cf_v2_ib_w2|cf_v2_ib_w3|cf_v2_ib_w4|cf_v2_ib_w5") + +;; Occupy 2 words. +(define_reservation "cf_v2_ib2" "(cf_v2_ib_w0+cf_v2_ib_w1)|(cf_v2_ib_w1+cf_v2_ib_w2)|(cf_v2_ib_w2+cf_v2_ib_w3)|(cf_v2_ib_w3+cf_v2_ib_w4)|(cf_v2_ib_w4+cf_v2_ib_w5)") + +;; Occupy 3 words. +(define_reservation "cf_v2_ib3" "(cf_v2_ib_w0+cf_v2_ib_w1+cf_v2_ib_w2)|(cf_v2_ib_w1+cf_v2_ib_w2+cf_v2_ib_w3)|(cf_v2_ib_w2+cf_v2_ib_w3+cf_v2_ib_w4)|(cf_v2_ib_w3+cf_v2_ib_w4+cf_v2_ib_w5)") + +;; Reservation to subscribe 1 word in the instruction buffer. If a given +;; word in the instruction buffer is subscribed, that means it is empty. +;; This reservation is used at the start of each cycle to setup the number +;; of prefetched instruction words in the instruction buffer. +;; At each cycle, given that memory bus is available (i.e. there is no +;; pending memory operation), IFP prefetches two instruction words into IB. +(define_insn_reservation "cf_v2_ib" 0 + (and (eq_attr "cpu" "cf_v2") + (eq_attr "type" "ib")) + "cf_v2_ib1") + +;; Operand Execution Pipeline +(define_automaton "cf_v2_oep") + +(define_cpu_unit "cf_v2_dsoc, cf_v2_agex" "cf_v2_oep") + +;; A memory unit that is reffered to as 'certain hardware resources' in +;; ColdFire reference manuals. This unit remains occupied for two cycles +;; after last dsoc cycle of a store - hence there is a 2 cycle delay between +;; two consecutive stores. +(define_automaton "cf_v2_chr") + +(define_cpu_unit "cf_v2_chr" "cf_v2_chr") + +;; Memory bus +(define_automaton "cf_v2_mem") + +;; When memory bus is subscribed, that implies that instruction buffer won't +;; get its portion this cycle. To model that we query if cf_v2_mem unit is +;; subscribed and adjust number of prefetched instruction words accordingly. +;; +(define_query_cpu_unit "cf_v2_mem" "cf_v2_mem") + +;; Register to register move. +;; Takes 1 cycle. +(define_reservation "cf_v2_move_00" + "cf_v2_dsoc+cf_v2_agex") + +;; Load from a memory location. +;; Takes 3 cycles. +(define_reservation "cf_v2_move_10" + "cf_v2_dsoc,cf_v2_agex,cf_v2_dsoc+cf_v2_mem,cf_v2_agex") + +;; Long load from a memory location. +;; Takes 2 cycles. +(define_reservation "cf_v2_move_l_10" + "cf_v2_dsoc+cf_v2_agex,cf_v2_dsoc+cf_v2_mem,cf_v2_agex") + +;; Load from an indexed location. +;; Takes 4 cycles. +(define_reservation "cf_v2_move_i0" + "cf_v2_dsoc,cf_v2_agex,cf_v2_agex,cf_v2_dsoc+cf_v2_mem,cf_v2_agex") + +;; Long load from an indexed location. +;; Takes 3 cycles. +(define_reservation "cf_v2_move_l_i0" + "cf_v2_dsoc+cf_v2_agex,cf_v2_agex,cf_v2_dsoc+cf_v2_mem,cf_v2_agex") + +;; Store to a memory location. +;; Takes 1 cycle. +(define_reservation "cf_v2_move_01" + "cf_v2_dsoc+cf_v2_agex+cf_v2_chr,cf_v2_mem+cf_v2_chr,cf_v2_chr") + +;; Store to an indexed location. +;; Takes 2 cycle. +(define_reservation "cf_v2_move_0i" + "cf_v2_dsoc+cf_v2_agex,cf_v2_agex+cf_v2_chr,cf_v2_mem+cf_v2_chr,cf_v2_chr") + +;; Load from a memory location and store to a memory location. +;; Takes 3 cycles +(define_reservation "cf_v2_move_11" + "cf_v2_dsoc,cf_v2_agex,cf_v2_dsoc+cf_v2_agex+cf_v2_mem+cf_v2_chr,cf_v2_mem+cf_v2_chr,cf_v2_chr") + +;; Long load from a memory location and store to a memory location. +;; Takes 2 cycles. +(define_reservation "cf_v2_move_l_11" + "cf_v2_dsoc+cf_v2_agex,cf_v2_dsoc+cf_v2_agex+cf_v2_mem+cf_v2_chr,cf_v2_mem+cf_v2_chr,cf_v2_chr") + +;; Load from an indexed location and store to a memory location. +;; Takes 4 cycles. +(define_reservation "cf_v2_move_i1" + "cf_v2_dsoc,cf_v2_agex,cf_v2_agex,cf_v2_dsoc+cf_v2_agex+cf_v2_mem+cf_v2_chr,cf_v2_mem+cf_v2_chr,cf_v2_chr") + +;; Long load from an indexed location and store to a memory location. +;; Takes 3 cycles. +(define_reservation "cf_v2_move_l_i1" + "cf_v2_dsoc+cf_v2_agex,cf_v2_agex,cf_v2_dsoc+cf_v2_agex+cf_v2_mem+cf_v2_chr,cf_v2_mem+cf_v2_chr,cf_v2_chr") + +;; Load from a memory location and store to an indexed location. +;; Takes 4 cycles. +(define_reservation "cf_v2_move_1i" + "cf_v2_dsoc,cf_v2_agex,cf_v2_dsoc+cf_v2_agex+cf_v2_mem,cf_v2_agex,cf_v2_mem") + +;; Long load from a memory location and store to an indexed location. +;; Takes 3 cycles. +(define_reservation "cf_v2_move_l_1i" + "cf_v2_dsoc+cf_v2_agex,cf_v2_dsoc+cf_v2_agex+cf_v2_mem,cf_v2_agex,cf_v2_mem") + +;; Lea operation for a memory location. +;; Takes 1 cycle. +(define_reservation "cf_v2_lea_10" + "cf_v2_dsoc+cf_v2_agex") + +;; Lea operation for an indexed location. +;; Takes 2 cycles. +(define_reservation "cf_v2_lea_i0" + "cf_v2_dsoc+cf_v2_agex,cf_v2_agex") + +;; Pea operation for a memory location. +;; Takes 2 cycle. +(define_reservation "cf_v2_pea_11" + "cf_v2_dsoc+cf_v2_agex,cf_v2_agex+cf_v2_chr,cf_v2_mem+cf_v2_chr,cf_v2_chr") + +;; Pea operation for an indexed location. +;; Takes 3 cycles. +(define_reservation "cf_v2_pea_i1" + "cf_v2_dsoc+cf_v2_agex,cf_v2_agex,cf_v2_agex+cf_v2_chr,cf_v2_mem+cf_v2_chr,cf_v2_chr") + +(define_automaton "cf_v2_emac") + +(define_cpu_unit "cf_v2_emac1,cf_v2_emac2,cf_v2_emac3,cf_v2_emac4" + "cf_v2_emac") + +;; Mul operation with register operands. +;; Takes 4 cycles. +(define_reservation "cf_v2_mul_00" + "cf_v2_dsoc,cf_v2_agex+cf_v2_emac1,cf_v2_emac2,cf_v2_emac3,cf_v2_emac4") + +;; Mul operation with implicit load from a memory location. +;; Takes 6 cycles. +(define_reservation "cf_v2_mul_10" + "cf_v2_dsoc,cf_v2_agex,cf_v2_dsoc+cf_v2_mem,cf_v2_agex+cf_v2_emac1,cf_v2_emac2,cf_v2_emac3,cf_v2_emac4") + +;; Mul operation with implicit load from an indexed location. +;; Takes 7 cycles. +(define_reservation "cf_v2_mul_i0" + "cf_v2_dsoc,cf_v2_agex,cf_v2_agex,cf_v2_dsoc+cf_v2_mem,cf_v2_agex+cf_v2_emac1,cf_v2_emac2,cf_v2_emac3,cf_v2_emac4") + +;; Instruction reservations. + +;; Below reservations are simple derivation from the above reservations. +;; Each reservation from the above expands into 3 reservations below - one +;; for each instruction size. +;; A number in the end of reservation's name is the size of the instruction. + +(define_insn_reservation "cf_v2_move_00_1" 1 + (and (and (and (eq_attr "cpu" "cf_v2") + (eq_attr "type2" "alu,alu_l,move,move_l")) + (eq (symbol_ref "get_attr_size (insn)") (const_int 1))) + (eq_attr "op_mem" "00")) + "cf_v2_ib1+cf_v2_move_00") + +(define_insn_reservation "cf_v2_move_00_2" 1 + (and (and (and (eq_attr "cpu" "cf_v2") + (eq_attr "type2" "alu,alu_l,move,move_l")) + (eq (symbol_ref "get_attr_size (insn)") (const_int 2))) + (eq_attr "op_mem" "00")) + "cf_v2_ib2+cf_v2_move_00") + +(define_insn_reservation "cf_v2_move_00_3" 1 + (and (and (and (eq_attr "cpu" "cf_v2") + (eq_attr "type2" "alu,alu_l,move,move_l")) + (eq (symbol_ref "get_attr_size (insn)") (const_int 3))) + (eq_attr "op_mem" "00")) + "cf_v2_ib3+cf_v2_move_00") + +(define_insn_reservation "cf_v2_move_10_1" 4 + (and (and (and (eq_attr "cpu" "cf_v2") + (eq_attr "type2" "alu_l,move")) + (eq (symbol_ref "get_attr_size (insn)") (const_int 1))) + (eq_attr "op_mem" "10")) + "cf_v2_ib1+cf_v2_move_10") + +(define_insn_reservation "cf_v2_move_10_2" 4 + (and (and (and (eq_attr "cpu" "cf_v2") + (eq_attr "type2" "alu_l,move")) + (eq (symbol_ref "get_attr_size (insn)") (const_int 2))) + (eq_attr "op_mem" "10")) + "cf_v2_ib2+cf_v2_move_10") + +(define_insn_reservation "cf_v2_move_10_3" 4 + (and (and (and (eq_attr "cpu" "cf_v2") + (eq_attr "type2" "alu_l,move")) + (eq (symbol_ref "get_attr_size (insn)") (const_int 3))) + (eq_attr "op_mem" "10")) + "cf_v2_ib3+cf_v2_move_10") + +(define_insn_reservation "cf_v2_move_l_10_1" 3 + (and (and (and (eq_attr "cpu" "cf_v2") + (eq_attr "type2" "move_l")) + (eq (symbol_ref "get_attr_size (insn)") (const_int 1))) + (eq_attr "op_mem" "10")) + "cf_v2_ib1+cf_v2_move_l_10") + +(define_insn_reservation "cf_v2_move_l_10_2" 3 + (and (and (and (eq_attr "cpu" "cf_v2") + (eq_attr "type2" "move_l")) + (eq (symbol_ref "get_attr_size (insn)") (const_int 2))) + (eq_attr "op_mem" "10")) + "cf_v2_ib2+cf_v2_move_l_10") + +(define_insn_reservation "cf_v2_move_l_10_3" 3 + (and (and (and (eq_attr "cpu" "cf_v2") + (eq_attr "type2" "move_l")) + (eq (symbol_ref "get_attr_size (insn)") (const_int 3))) + (eq_attr "op_mem" "10")) + "cf_v2_ib3+cf_v2_move_l_10") + +(define_insn_reservation "cf_v2_move_i0_2" 5 + (and (and (and (eq_attr "cpu" "cf_v2") + (eq_attr "type2" "alu_l,move")) + (eq (symbol_ref "get_attr_size (insn)") (const_int 2))) + (eq_attr "op_mem" "i0")) + "cf_v2_ib2+cf_v2_move_i0") + +(define_insn_reservation "cf_v2_move_i0_3" 5 + (and (and (and (eq_attr "cpu" "cf_v2") + (eq_attr "type2" "alu_l,move")) + (eq (symbol_ref "get_attr_size (insn)") (const_int 3))) + (eq_attr "op_mem" "i0")) + "cf_v2_ib3+cf_v2_move_i0") + +(define_insn_reservation "cf_v2_move_l_i0_2" 4 + (and (and (and (eq_attr "cpu" "cf_v2") + (eq_attr "type2" "move_l")) + (eq (symbol_ref "get_attr_size (insn)") (const_int 2))) + (eq_attr "op_mem" "i0")) + "cf_v2_ib2+cf_v2_move_l_i0") + +(define_insn_reservation "cf_v2_move_l_i0_3" 4 + (and (and (and (eq_attr "cpu" "cf_v2") + (eq_attr "type2" "move_l")) + (eq (symbol_ref "get_attr_size (insn)") (const_int 3))) + (eq_attr "op_mem" "i0")) + "cf_v2_ib3+cf_v2_move_l_i0") + +(define_insn_reservation "cf_v2_move_01_1" 0 + (and (and (and (eq_attr "cpu" "cf_v2") + (eq_attr "type2" "alu_l,move,move_l")) + (eq (symbol_ref "get_attr_size (insn)") (const_int 1))) + (eq_attr "op_mem" "01")) + "cf_v2_ib1+cf_v2_move_01") + +(define_insn_reservation "cf_v2_move_01_2" 0 + (and (and (and (eq_attr "cpu" "cf_v2") + (eq_attr "type2" "alu_l,move,move_l")) + (eq (symbol_ref "get_attr_size (insn)") (const_int 2))) + (eq_attr "op_mem" "01")) + "cf_v2_ib2+cf_v2_move_01") + +(define_insn_reservation "cf_v2_move_01_3" 0 + (and (and (and (eq_attr "cpu" "cf_v2") + (eq_attr "type2" "alu_l,move,move_l")) + (eq (symbol_ref "get_attr_size (insn)") (const_int 3))) + (eq_attr "op_mem" "01")) + "cf_v2_ib3+cf_v2_move_01") + +(define_insn_reservation "cf_v2_move_0i_2" 0 + (and (and (and (eq_attr "cpu" "cf_v2") + (eq_attr "type2" "alu_l,move,move_l")) + (eq (symbol_ref "get_attr_size (insn)") (const_int 2))) + (eq_attr "op_mem" "0i")) + "cf_v2_ib2+cf_v2_move_0i") + +(define_insn_reservation "cf_v2_move_0i_3" 0 + (and (and (and (eq_attr "cpu" "cf_v2") + (eq_attr "type2" "alu_l,move,move_l")) + (eq (symbol_ref "get_attr_size (insn)") (const_int 3))) + (eq_attr "op_mem" "0i")) + "cf_v2_ib3+cf_v2_move_0i") + +(define_insn_reservation "cf_v2_move_11_1" 0 + (and (and (and (eq_attr "cpu" "cf_v2") + (eq_attr "type2" "alu_l,move")) + (eq (symbol_ref "get_attr_size (insn)") (const_int 1))) + (eq_attr "op_mem" "11")) + "cf_v2_ib1+cf_v2_move_11") + +(define_insn_reservation "cf_v2_move_11_2" 0 + (and (and (and (eq_attr "cpu" "cf_v2") + (eq_attr "type2" "alu_l,move")) + (eq (symbol_ref "get_attr_size (insn)") (const_int 2))) + (eq_attr "op_mem" "11")) + "cf_v2_ib2+cf_v2_move_11") + +(define_insn_reservation "cf_v2_move_11_3" 0 + (and (and (and (eq_attr "cpu" "cf_v2") + (eq_attr "type2" "alu_l,move")) + (eq (symbol_ref "get_attr_size (insn)") (const_int 3))) + (eq_attr "op_mem" "11")) + "cf_v2_ib3+cf_v2_move_11") + +(define_insn_reservation "cf_v2_move_l_11_1" 0 + (and (and (and (eq_attr "cpu" "cf_v2") + (eq_attr "type2" "move_l")) + (eq (symbol_ref "get_attr_size (insn)") (const_int 1))) + (eq_attr "op_mem" "11")) + "cf_v2_ib1+cf_v2_move_l_11") + +(define_insn_reservation "cf_v2_move_l_11_2" 0 + (and (and (and (eq_attr "cpu" "cf_v2") + (eq_attr "type2" "move_l")) + (eq (symbol_ref "get_attr_size (insn)") (const_int 2))) + (eq_attr "op_mem" "11")) + "cf_v2_ib2+cf_v2_move_l_11") + +(define_insn_reservation "cf_v2_move_l_11_3" 0 + (and (and (and (eq_attr "cpu" "cf_v2") + (eq_attr "type2" "move_l")) + (eq (symbol_ref "get_attr_size (insn)") (const_int 3))) + (eq_attr "op_mem" "11")) + "cf_v2_ib3+cf_v2_move_l_11") + +(define_insn_reservation "cf_v2_move_i1_2" 0 + (and (and (and (eq_attr "cpu" "cf_v2") + (eq_attr "type2" "alu_l,move")) + (eq (symbol_ref "get_attr_size (insn)") (const_int 2))) + (eq_attr "op_mem" "i1")) + "cf_v2_ib2+cf_v2_move_i1") + +(define_insn_reservation "cf_v2_move_i1_3" 0 + (and (and (and (eq_attr "cpu" "cf_v2") + (eq_attr "type2" "alu_l,move")) + (eq (symbol_ref "get_attr_size (insn)") (const_int 3))) + (eq_attr "op_mem" "i1")) + "cf_v2_ib3+cf_v2_move_i1") + +(define_insn_reservation "cf_v2_move_l_i1_2" 0 + (and (and (and (eq_attr "cpu" "cf_v2") + (eq_attr "type2" "move_l")) + (eq (symbol_ref "get_attr_size (insn)") (const_int 2))) + (eq_attr "op_mem" "i1")) + "cf_v2_ib2+cf_v2_move_l_i1") + +(define_insn_reservation "cf_v2_move_l_i1_3" 0 + (and (and (and (eq_attr "cpu" "cf_v2") + (eq_attr "type2" "move_l")) + (eq (symbol_ref "get_attr_size (insn)") (const_int 3))) + (eq_attr "op_mem" "i1")) + "cf_v2_ib3+cf_v2_move_l_i1") + +(define_insn_reservation "cf_v2_move_1i_2" 0 + (and (and (and (eq_attr "cpu" "cf_v2") + (eq_attr "type2" "alu_l,move")) + (eq (symbol_ref "get_attr_size (insn)") (const_int 2))) + (eq_attr "op_mem" "1i")) + "cf_v2_ib2+cf_v2_move_1i") + +(define_insn_reservation "cf_v2_move_1i_3" 0 + (and (and (and (eq_attr "cpu" "cf_v2") + (eq_attr "type2" "alu_l,move")) + (eq (symbol_ref "get_attr_size (insn)") (const_int 3))) + (eq_attr "op_mem" "1i")) + "cf_v2_ib3+cf_v2_move_1i") + +(define_insn_reservation "cf_v2_move_l_1i_2" 0 + (and (and (and (eq_attr "cpu" "cf_v2") + (eq_attr "type2" "move_l")) + (eq (symbol_ref "get_attr_size (insn)") (const_int 2))) + (eq_attr "op_mem" "1i")) + "cf_v2_ib2+cf_v2_move_l_1i") + +(define_insn_reservation "cf_v2_move_l_1i_3" 0 + (and (and (and (eq_attr "cpu" "cf_v2") + (eq_attr "type2" "move_l")) + (eq (symbol_ref "get_attr_size (insn)") (const_int 3))) + (eq_attr "op_mem" "1i")) + "cf_v2_ib3+cf_v2_move_l_1i") + +(define_insn_reservation "cf_v2_lea_10_1" 1 + (and (and (and (eq_attr "cpu" "cf_v2") + (eq_attr "type2" "lea")) + (eq (symbol_ref "get_attr_size (insn)") (const_int 1))) + (eq_attr "op_mem" "10")) + "cf_v2_ib1+cf_v2_lea_10") + +(define_insn_reservation "cf_v2_lea_10_2" 1 + (and (and (and (eq_attr "cpu" "cf_v2") + (eq_attr "type2" "lea")) + (eq (symbol_ref "get_attr_size (insn)") (const_int 2))) + (eq_attr "op_mem" "10")) + "cf_v2_ib2+cf_v2_lea_10") + +(define_insn_reservation "cf_v2_lea_10_3" 1 + (and (and (and (eq_attr "cpu" "cf_v2") + (eq_attr "type2" "lea")) + (eq (symbol_ref "get_attr_size (insn)") (const_int 3))) + (eq_attr "op_mem" "10")) + "cf_v2_ib3+cf_v2_lea_10") + +(define_insn_reservation "cf_v2_lea_i0_2" 2 + (and (and (and (eq_attr "cpu" "cf_v2") + (eq_attr "type2" "lea")) + (eq (symbol_ref "get_attr_size (insn)") (const_int 2))) + (eq_attr "op_mem" "i0")) + "cf_v2_ib2+cf_v2_lea_i0") + +(define_insn_reservation "cf_v2_lea_i0_3" 2 + (and (and (and (eq_attr "cpu" "cf_v2") + (eq_attr "type2" "lea")) + (eq (symbol_ref "get_attr_size (insn)") (const_int 3))) + (eq_attr "op_mem" "i0")) + "cf_v2_ib3+cf_v2_lea_i0") + +(define_insn_reservation "cf_v2_pea_11_1" 0 + (and (and (and (eq_attr "cpu" "cf_v2") + (eq_attr "type2" "pea")) + (eq (symbol_ref "get_attr_size (insn)") (const_int 1))) + (eq_attr "op_mem" "11")) + "cf_v2_ib1+cf_v2_pea_11") + +(define_insn_reservation "cf_v2_pea_11_2" 0 + (and (and (and (eq_attr "cpu" "cf_v2") + (eq_attr "type2" "pea")) + (eq (symbol_ref "get_attr_size (insn)") (const_int 2))) + (eq_attr "op_mem" "11")) + "cf_v2_ib2+cf_v2_pea_11") + +(define_insn_reservation "cf_v2_pea_11_3" 0 + (and (and (and (eq_attr "cpu" "cf_v2") + (eq_attr "type2" "pea")) + (eq (symbol_ref "get_attr_size (insn)") (const_int 3))) + (eq_attr "op_mem" "11")) + "cf_v2_ib3+cf_v2_pea_11") + +(define_insn_reservation "cf_v2_pea_i1_2" 0 + (and (and (and (eq_attr "cpu" "cf_v2") + (eq_attr "type2" "pea")) + (eq (symbol_ref "get_attr_size (insn)") (const_int 2))) + (eq_attr "op_mem" "i1")) + "cf_v2_ib2+cf_v2_pea_i1") + +(define_insn_reservation "cf_v2_pea_i1_3" 0 + (and (and (and (eq_attr "cpu" "cf_v2") + (eq_attr "type2" "pea")) + (eq (symbol_ref "get_attr_size (insn)") (const_int 3))) + (eq_attr "op_mem" "i1")) + "cf_v2_ib3+cf_v2_pea_i1") + +(define_insn_reservation "cf_v2_mul_00_1" 4 + (and (and (and (eq_attr "cpu" "cf_v2") + (eq_attr "type2" "mul")) + (eq (symbol_ref "get_attr_size (insn)") (const_int 1))) + (eq_attr "op_mem" "00")) + "cf_v2_ib1+cf_v2_mul_00") + +(define_insn_reservation "cf_v2_mul_00_2" 4 + (and (and (and (eq_attr "cpu" "cf_v2") + (eq_attr "type2" "mul")) + (eq (symbol_ref "get_attr_size (insn)") (const_int 2))) + (eq_attr "op_mem" "00")) + "cf_v2_ib2+cf_v2_mul_00") + +(define_insn_reservation "cf_v2_mul_00_3" 4 + (and (and (and (eq_attr "cpu" "cf_v2") + (eq_attr "type2" "mul")) + (eq (symbol_ref "get_attr_size (insn)") (const_int 3))) + (eq_attr "op_mem" "00")) + "cf_v2_ib3+cf_v2_mul_00") + +(define_insn_reservation "cf_v2_mul_10_1" 6 + (and (and (and (eq_attr "cpu" "cf_v2") + (eq_attr "type2" "mul")) + (eq (symbol_ref "get_attr_size (insn)") (const_int 1))) + (eq_attr "op_mem" "10")) + "cf_v2_ib1+cf_v2_mul_10") + +(define_insn_reservation "cf_v2_mul_10_2" 6 + (and (and (and (eq_attr "cpu" "cf_v2") + (eq_attr "type2" "mul")) + (eq (symbol_ref "get_attr_size (insn)") (const_int 2))) + (eq_attr "op_mem" "10")) + "cf_v2_ib2+cf_v2_mul_10") + +(define_insn_reservation "cf_v2_mul_10_3" 6 + (and (and (and (eq_attr "cpu" "cf_v2") + (eq_attr "type2" "mul")) + (eq (symbol_ref "get_attr_size (insn)") (const_int 3))) + (eq_attr "op_mem" "10")) + "cf_v2_ib3+cf_v2_mul_10") + +(define_insn_reservation "cf_v2_mul_i0_2" 7 + (and (and (and (eq_attr "cpu" "cf_v2") + (eq_attr "type2" "mul")) + (eq (symbol_ref "get_attr_size (insn)") (const_int 2))) + (eq_attr "op_mem" "i0")) + "cf_v2_ib2+cf_v2_mul_i0") + +(define_insn_reservation "cf_v2_mul_i0_3" 7 + (and (and (and (eq_attr "cpu" "cf_v2") + (eq_attr "type2" "mul")) + (eq (symbol_ref "get_attr_size (insn)") (const_int 3))) + (eq_attr "op_mem" "i0")) + "cf_v2_ib3+cf_v2_mul_i0") + +;; ??? As return reads target address from stack, use a mem-read reservation +;; for it. +(define_reservation "cf_v2_rts" "cf_v2_move_10") + +;; ??? It's not clear what the core does during these 5 cycles. +;; Luckily, we don't care that much about an insn that won't be moved. +(define_insn_reservation "cf_v2_rts_1" 5 + (and (and (eq_attr "cpu" "cf_v2") + (eq_attr "type2" "rts")) + (eq (symbol_ref "get_attr_size (insn)") (const_int 1))) + "cf_v2_ib1+cf_v2_rts") + +;; Call instructions reservations. + +;; ??? It's not clear what reservation is best to use for calls. +;; For now we use mem-write + return reservations to reflect the fact of +;; pushing and poping return address to and from the stack. + +(define_insn_reservation "cf_v2_call_1" 3 + (and (and (eq_attr "cpu" "cf_v2") + (eq_attr "type2" "call")) + (eq (symbol_ref "get_attr_size (insn)") (const_int 1))) + "cf_v2_ib1+cf_v2_move_10,cf_v2_rts") + +(define_insn_reservation "cf_v2_call_2" 3 + (and (and (eq_attr "cpu" "cf_v2") + (eq_attr "type2" "call")) + (eq (symbol_ref "get_attr_size (insn)") (const_int 2))) + "cf_v2_ib2+cf_v2_move_10,cf_v2_rts") + +(define_insn_reservation "cf_v2_call_3" 3 + (and (and (eq_attr "cpu" "cf_v2") + (eq_attr "type2" "call")) + (eq (symbol_ref "get_attr_size (insn)") (const_int 3))) + "cf_v2_ib3+cf_v2_move_10,cf_v2_rts") + +;; Branch reservations. + +;; ??? Branch reservations are unclear to me so far. Luckily, we don't care +;; ??? that much about branches. +(define_reservation "cf_v2_bcc" "cf_v2_move_00") + +(define_insn_reservation "cf_v2_bcc_1" 2 + (and (and (eq_attr "cpu" "cf_v2") + (eq_attr "type2" "bcc")) + (eq (symbol_ref "get_attr_size (insn)") (const_int 1))) + "cf_v2_ib1+cf_v2_bcc") + +(define_insn_reservation "cf_v2_bcc_2" 2 + (and (and (eq_attr "cpu" "cf_v2") + (eq_attr "type2" "bcc")) + (eq (symbol_ref "get_attr_size (insn)") (const_int 2))) + "cf_v2_ib2+cf_v2_bcc") + +(define_insn_reservation "cf_v2_bcc_3" 2 + (and (and (eq_attr "cpu" "cf_v2") + (eq_attr "type2" "bcc")) + (eq (symbol_ref "get_attr_size (insn)") (const_int 3))) + "cf_v2_ib3+cf_v2_bcc") + +(define_reservation "cf_v2_bra" "cf_v2_move_01") + +(define_insn_reservation "cf_v2_bra_1" 2 + (and (and (eq_attr "cpu" "cf_v2") + (eq_attr "type2" "bra")) + (eq (symbol_ref "get_attr_size (insn)") (const_int 1))) + "cf_v2_ib1+cf_v2_bra") + +(define_insn_reservation "cf_v2_bra_2" 2 + (and (and (eq_attr "cpu" "cf_v2") + (eq_attr "type2" "bra")) + (eq (symbol_ref "get_attr_size (insn)") (const_int 2))) + "cf_v2_ib2+cf_v2_bra") + +(define_insn_reservation "cf_v2_bra_3" 2 + (and (and (eq_attr "cpu" "cf_v2") + (eq_attr "type2" "bra")) + (eq (symbol_ref "get_attr_size (insn)") (const_int 3))) + "cf_v2_ib3+cf_v2_bra") + +;; Computed jump. +;; Takes 3 cycles. +(define_reservation "cf_v2_jmp" + "cf_v2_dsoc,cf_v2_agex,cf_v2_dsoc,cf_v2_agex") + +(define_insn_reservation "cf_v2_jmp_1" 3 + (and (and (eq_attr "cpu" "cf_v2") + (eq_attr "type2" "jmp")) + (eq (symbol_ref "get_attr_size (insn)") (const_int 1))) + "cf_v2_ib1+cf_v2_jmp") + +(define_insn_reservation "cf_v2_jmp_2" 3 + (and (and (eq_attr "cpu" "cf_v2") + (eq_attr "type2" "jmp")) + (eq (symbol_ref "get_attr_size (insn)") (const_int 2))) + "cf_v2_ib2+cf_v2_jmp") + +(define_insn_reservation "cf_v2_jmp_3" 3 + (and (and (eq_attr "cpu" "cf_v2") + (eq_attr "type2" "jmp")) + (eq (symbol_ref "get_attr_size (insn)") (const_int 3))) + "cf_v2_ib3+cf_v2_jmp") + +;; Misc reservations. + +(define_insn_reservation "cf_v2_unlk_1" 2 + (and (and (eq_attr "cpu" "cf_v2") + (eq_attr "type2" "unlk")) + (eq (symbol_ref "get_attr_size (insn)") (const_int 1))) + "cf_v2_ib1+cf_v2_move_l_10") + +;; This automaton is used to gather statistics on insns that need reservations. +(define_automaton "cf_v2_guess") + +(define_query_cpu_unit "cf_v2_guess" "cf_v2_guess") + +;; Dummy reservation for instructions that are not handled yet. + +(define_insn_reservation "cf_v2_guess_1" 1 + (and (and (eq_attr "cpu" "cf_v2") + (eq_attr "guess" "yes")) + (eq (symbol_ref "get_attr_size (insn)") (const_int 1))) + "cf_v2_ib1+cf_v2_guess+cf_v2_dsoc+cf_v2_agex") + +(define_insn_reservation "cf_v2_guess_2" 1 + (and (and (eq_attr "cpu" "cf_v2") + (eq_attr "guess" "yes")) + (eq (symbol_ref "get_attr_size (insn)") (const_int 2))) + "cf_v2_ib2+cf_v2_guess+cf_v2_dsoc+cf_v2_agex") + +(define_insn_reservation "cf_v2_guess_3" 1 + (and (and (eq_attr "cpu" "cf_v2") + (eq_attr "guess" "yes")) + (eq (symbol_ref "get_attr_size (insn)") (const_int 3))) + "cf_v2_ib3+cf_v2_guess+cf_v2_dsoc+cf_v2_agex") diff --git a/gcc/config/m68k/m68k-protos.h b/gcc/config/m68k/m68k-protos.h index 7d1ea97ce0c..bd039077b7d 100644 --- a/gcc/config/m68k/m68k-protos.h +++ b/gcc/config/m68k/m68k-protos.h @@ -73,6 +73,7 @@ extern enum attr_opy_type m68k_sched_attr_opy_type (rtx, int); extern int m68k_sched_attr_size (rtx); extern enum attr_op_mem m68k_sched_attr_op_mem (rtx); extern enum attr_type m68k_sched_branch_type (rtx); +extern enum attr_type2 m68k_sched_attr_type2 (rtx); #endif /* HAVE_ATTR_cpu */ #endif /* RTX_CODE */ diff --git a/gcc/config/m68k/m68k.c b/gcc/config/m68k/m68k.c index 952b94783d4..142c8aa959e 100644 --- a/gcc/config/m68k/m68k.c +++ b/gcc/config/m68k/m68k.c @@ -43,6 +43,9 @@ along with GCC; see the file COPYING3. If not see #include "debug.h" #include "flags.h" #include "df.h" +/* ??? Need to add a dependency between m68k.o and sched-int.h. */ +#include "sched-int.h" +#include "insn-codes.h" enum reg_class regno_reg_class[] = { @@ -118,6 +121,14 @@ struct m68k_address { int scale; }; +static int m68k_sched_adjust_cost (rtx, rtx, rtx, int); +static int m68k_sched_variable_issue (FILE *, int, rtx, int); +static void m68k_sched_md_init_global (FILE *, int, int); +static void m68k_sched_md_finish_global (FILE *, int); +static void m68k_sched_md_init (FILE *, int, int); +static void m68k_sched_dfa_pre_advance_cycle (void); +static void m68k_sched_dfa_post_advance_cycle (void); + static bool m68k_handle_option (size_t, const char *, int); static rtx find_addr_reg (rtx); static const char *singlemove_string (rtx *); @@ -185,6 +196,27 @@ int m68k_last_compare_had_fp_operands; #undef TARGET_ASM_FILE_START_APP_OFF #define TARGET_ASM_FILE_START_APP_OFF true +#undef TARGET_SCHED_ADJUST_COST +#define TARGET_SCHED_ADJUST_COST m68k_sched_adjust_cost + +#undef TARGET_SCHED_VARIABLE_ISSUE +#define TARGET_SCHED_VARIABLE_ISSUE m68k_sched_variable_issue + +#undef TARGET_SCHED_INIT_GLOBAL +#define TARGET_SCHED_INIT_GLOBAL m68k_sched_md_init_global + +#undef TARGET_SCHED_FINISH_GLOBAL +#define TARGET_SCHED_FINISH_GLOBAL m68k_sched_md_finish_global + +#undef TARGET_SCHED_INIT +#define TARGET_SCHED_INIT m68k_sched_md_init + +#undef TARGET_SCHED_DFA_PRE_ADVANCE_CYCLE +#define TARGET_SCHED_DFA_PRE_ADVANCE_CYCLE m68k_sched_dfa_pre_advance_cycle + +#undef TARGET_SCHED_DFA_POST_ADVANCE_CYCLE +#define TARGET_SCHED_DFA_POST_ADVANCE_CYCLE m68k_sched_dfa_post_advance_cycle + #undef TARGET_HANDLE_OPTION #define TARGET_HANDLE_OPTION m68k_handle_option @@ -4971,3 +5003,451 @@ m68k_sched_branch_type (rtx insn) return type; } + +/* Implement type2 attribute. */ +enum attr_type2 +m68k_sched_attr_type2 (rtx insn) +{ + switch (get_attr_type1 (insn)) + { + case TYPE1_ALU_REG1: + case TYPE1_ALU_REGX: + return TYPE2_ALU; + + case TYPE1_ALU_L: + case TYPE1_ALUQ_L: + case TYPE1_CMP_L: + return TYPE2_ALU_L; + + case TYPE1_BCC: + return TYPE2_BCC; + + case TYPE1_BRA: + return TYPE2_BRA; + + case TYPE1_BSR: + case TYPE1_JSR: + return TYPE2_CALL; + + case TYPE1_JMP: + return TYPE2_JMP; + + case TYPE1_LEA: + return TYPE2_LEA; + + case TYPE1_CLR: + case TYPE1_MOV3Q_L: + case TYPE1_MOVE: + case TYPE1_MOVEQ_L: + case TYPE1_TST: + return TYPE2_MOVE; + + case TYPE1_MOVE_L: + case TYPE1_TST_L: + return TYPE2_MOVE_L; + + case TYPE1_MUL_W: + case TYPE1_MUL_L: + return TYPE2_MUL; + + case TYPE1_PEA: + return TYPE2_PEA; + + case TYPE1_RTS: + return TYPE2_RTS; + + case TYPE1_UNLK: + return TYPE2_UNLK; + + default: + gcc_assert (get_attr_guess (insn) == GUESS_YES); + return TYPE2_UNKNOWN; + } +} + +/* An empty state that is used in m68k_sched_adjust_cost. */ +static state_t sched_adjust_cost_state; + +/* Implement adjust_cost scheduler hook. + Return adjusted COST of dependency LINK between DEF_INSN and INSN. */ +static int +m68k_sched_adjust_cost (rtx insn, rtx link ATTRIBUTE_UNUSED, rtx def_insn, + int cost) +{ + int delay; + + if (recog_memoized (def_insn) < 0 + || recog_memoized (insn) < 0) + return cost; + + /* Don't try to issue INSN earlier than DFA permits. + This is especially useful for instructions that write to memory, + as their true dependence (default) latency is better to be set to 0 + to workaround alias analysis limitations. + This is, in fact, a machine independent tweak, so, probably, + it should be moved to haifa-sched.c: insn_cost (). */ + + delay = min_insn_conflict_delay (sched_adjust_cost_state, def_insn, insn); + if (delay > cost) + cost = delay; + + return cost; +} + +/* Size of the instruction buffer in words. */ +static int sched_ib_size; + +/* Number of filled words in the instruction buffer. */ +static int sched_ib_filled; + +/* An insn that reserves (marks empty) one word in the instruction buffer. */ +static rtx sched_ib_insn; + +/* ID of memory unit. */ +static int sched_mem_unit_code; + +/* Implementation of the targetm.sched.variable_issue () hook. + It is called after INSN was issued. It returns the number of insns + that can possibly get scheduled on the current cycle. + It is used here to determine the effect of INSN on the instruction + buffer. */ +static int +m68k_sched_variable_issue (FILE *sched_dump ATTRIBUTE_UNUSED, + int sched_verbose ATTRIBUTE_UNUSED, + rtx insn, int can_issue_more) +{ + int insn_size; + + if (recog_memoized (insn) >= 0) + { + insn_size = get_attr_size (insn); + + gcc_assert (insn_size <= sched_ib_filled); + + --can_issue_more; + } + else if (GET_CODE (PATTERN (insn)) == ASM_INPUT + || asm_noperands (PATTERN (insn)) >= 0) + insn_size = sched_ib_filled; + else + insn_size = 0; + + sched_ib_filled -= insn_size; + + return can_issue_more; +} + +/* Statistics gatherer. */ + +typedef enum + { + /* Something needs to be done for this insn. */ + SCHED_DUMP_TODO, + + /* Support for this insn is complete. */ + SCHED_DUMP_DONE, + + /* This insn didn't require much effort to support it. */ + SCHED_DUMP_NOTHING + } sched_dump_class_def; + +/* Pointer to functions that classifies insns into 3 above classes. */ +typedef sched_dump_class_def (*sched_dump_class_func_t) (rtx); + +/* Return statistical type of INSN regarding splits. */ +static sched_dump_class_def +sched_dump_split_class (rtx insn) +{ + int i; + + i = recog_memoized (insn); + gcc_assert (i >= 0); + + switch (get_attr_split (insn)) + { + case SPLIT_TODO: + return SCHED_DUMP_TODO; + + case SPLIT_DONE: + return SCHED_DUMP_DONE; + + case SPLIT_NOTHING: + return SCHED_DUMP_NOTHING; + + default: + gcc_unreachable (); + } +} + +/* ID of the guess unit. */ +static int sched_dump_dfa_guess_unit_code; + +/* DFA state for use in sched_dump_dfa_class (). */ +static state_t sched_dump_dfa_state; + +/* Return statistical type of INSN regarding DFA reservations. */ +static sched_dump_class_def +sched_dump_dfa_class (rtx insn) +{ + int i; + + i = recog_memoized (insn); + gcc_assert (i >= 0 && insn_has_dfa_reservation_p (insn)); + + if (sched_dump_split_class (insn) == SCHED_DUMP_TODO) + /* Insn is not yet ready for reservations. */ + return SCHED_DUMP_NOTHING; + + state_reset (sched_dump_dfa_state); + + if (state_transition (sched_dump_dfa_state, insn) >= 0) + gcc_unreachable (); + + if (cpu_unit_reservation_p (sched_dump_dfa_state, + sched_dump_dfa_guess_unit_code)) + return SCHED_DUMP_TODO; + + return SCHED_DUMP_DONE; +} + +/* Dump statistics on current function into file DUMP_FILENAME and prefix + each entry with PREFIX. + Instructions are classified with DUMP_CLASS. */ +static void +m68k_sched_dump (sched_dump_class_func_t dump_class, + const char *prefix, FILE *dump) +{ + sbitmap present; + int *todos; + int *dones; + int *nothings; + rtx insn; + + gcc_assert (dump != NULL); + + present = sbitmap_alloc (CODE_FOR_nothing); + sbitmap_zero (present); + + todos = xcalloc (CODE_FOR_nothing, sizeof (*todos)); + dones = xcalloc (CODE_FOR_nothing, sizeof (*dones)); + nothings = xcalloc (CODE_FOR_nothing, sizeof (*nothings)); + + /* Gather statistics. */ + for (insn = get_insns (); insn != NULL_RTX; insn = NEXT_INSN (insn)) + { + if (INSN_P (insn) && recog_memoized (insn) >= 0) + { + enum insn_code code; + + code = INSN_CODE (insn); + gcc_assert (code < CODE_FOR_nothing); + + SET_BIT (present, code); + + switch (dump_class (insn)) + { + case SCHED_DUMP_TODO: + ++todos[code]; + break; + + case SCHED_DUMP_DONE: + ++dones[code]; + break; + + case SCHED_DUMP_NOTHING: + ++nothings[code]; + break; + } + } + } + + /* Print statisctics. */ + { + unsigned int i; + sbitmap_iterator si; + int total_todo; + int total_done; + int total_nothing; + + total_todo = 0; + total_done = 0; + total_nothing = 0; + + EXECUTE_IF_SET_IN_SBITMAP (present, 0, i, si) + { + int todo; + int done; + int nothing; + enum insn_code code; + + code = (enum insn_code) i; + + todo = todos[code]; + done = dones[code]; + nothing = nothings[code]; + + total_todo += todo; + total_done += done; + total_nothing += nothing; + + if (todo != 0) + { + fprintf (dump, + "%s: %3d: %d / %d / %d ;", + prefix, code, todo, done, nothing); + + { + const char *name; + + name = get_insn_name (code); + + if (name != NULL) + fprintf (dump, " {%s}\n", name); + else + fprintf (dump, " {unknown}\n"); + } + } + } + + gcc_assert (CODE_FOR_nothing < 999); + + fprintf (dump, + "%s: 999: %d / %d / %d ; {total}\n", + prefix, total_todo, total_done, total_nothing); + } + + free (nothings); + nothings = NULL; + free (dones); + dones = NULL; + free (todos); + todos = NULL; + + sbitmap_free (present); + present = NULL; +} + +/* Implementation of targetm.sched.md_init_global () hook. + It is invoked once per scheduling pass and is used here + to initialize scheduler constants. */ +static void +m68k_sched_md_init_global (FILE *sched_dump ATTRIBUTE_UNUSED, + int sched_verbose ATTRIBUTE_UNUSED, + int n_insns ATTRIBUTE_UNUSED) +{ + /* Init branch types. */ + { + rtx insn; + + sched_branch_type = xcalloc (get_max_uid () + 1, + sizeof (*sched_branch_type)); + + for (insn = get_insns (); insn != NULL_RTX; insn = NEXT_INSN (insn)) + { + if (JUMP_P (insn)) + /* !!! FIXME: Implement real scan here. */ + sched_branch_type[INSN_UID (insn)] = TYPE_BCC; + } + } + + if (reload_completed && sched_verbose >= 8) + /* Dump statistics. */ + { + m68k_sched_dump (sched_dump_split_class, "m68k_sched_split", + sched_dump); + + sched_dump_dfa_guess_unit_code = get_cpu_unit_code ("cf_v2_guess"); + sched_dump_dfa_state = alloca (state_size ()); + + m68k_sched_dump (sched_dump_dfa_class, "m68k_sched_dfa", + sched_dump); + + sched_dump_dfa_state = NULL; + sched_dump_dfa_guess_unit_code = 0; + } + + /* Setup target cpu. */ + switch (m68k_sched_cpu) + { + case CPU_CF_V2: + sched_ib_size = 6; + sched_mem_unit_code = get_cpu_unit_code ("cf_v2_mem"); + break; + + default: + gcc_unreachable (); + } + + sched_adjust_cost_state = xmalloc (state_size ()); + state_reset (sched_adjust_cost_state); + + start_sequence (); + emit_insn (gen_ib ()); + sched_ib_insn = get_insns (); + end_sequence (); +} + +/* Scheduling pass is now finished. Free/reset static variables. */ +static void +m68k_sched_md_finish_global (FILE *dump ATTRIBUTE_UNUSED, + int verbose ATTRIBUTE_UNUSED) +{ + sched_ib_insn = NULL; + + free (sched_adjust_cost_state); + sched_adjust_cost_state = NULL; + + sched_mem_unit_code = 0; + sched_ib_size = 0; + + free (sched_branch_type); + sched_branch_type = NULL; +} + +/* Implementation of targetm.sched.md_init () hook. + It is invoked each time scheduler starts on the new block (basic block or + extended basic block). */ +static void +m68k_sched_md_init (FILE *sched_dump ATTRIBUTE_UNUSED, + int sched_verbose ATTRIBUTE_UNUSED, + int n_insns ATTRIBUTE_UNUSED) +{ + /* haifa-sched.c: schedule_block () calls advance_cycle () just before + the first cycle. Workaround that. */ + sched_ib_filled = -2; +} + +/* Implementation of targetm.sched.dfa_pre_advance_cycle () hook. + It is invoked just before current cycle finishes and is used here + to track if instruction buffer got its two words this cycle. */ +static void +m68k_sched_dfa_pre_advance_cycle (void) +{ + if (!cpu_unit_reservation_p (curr_state, sched_mem_unit_code)) + { + sched_ib_filled += 2; + + if (sched_ib_filled > sched_ib_size) + sched_ib_filled = sched_ib_size; + } +} + +/* Implementation of targetm.sched.dfa_post_advance_cycle () hook. + It is invoked just after new cycle begins and is used here + to setup number of filled words in the instruction buffer so that + instructions which won't have all their words prefetched would be + stalled for a cycle. */ +static void +m68k_sched_dfa_post_advance_cycle (void) +{ + int i; + int n; + + /* Setup number of prefetched instruction words in the instruction + buffer. */ + for (i = sched_ib_filled, n = sched_ib_size; i < n; ++i) + { + if (state_transition (curr_state, sched_ib_insn) >= 0) + gcc_unreachable (); + } +} diff --git a/gcc/config/m68k/m68k.h b/gcc/config/m68k/m68k.h index c077c35df71..d8e1d3aa829 100644 --- a/gcc/config/m68k/m68k.h +++ b/gcc/config/m68k/m68k.h @@ -1148,3 +1148,4 @@ extern M68K_CONST_METHOD m68k_const_method (HOST_WIDE_INT); extern void m68k_emit_move_double (rtx [2]); +#define CPU_UNITS_QUERY 1 diff --git a/gcc/config/m68k/m68k.md b/gcc/config/m68k/m68k.md index 68053b33b70..c3f3138bf5e 100644 --- a/gcc/config/m68k/m68k.md +++ b/gcc/config/m68k/m68k.md @@ -7729,3 +7729,5 @@ "" "#" [(set_attr "type" "ib")]) + +(include "cf.md") -- 2.11.0