OSDN Git Service

* config/m68k/m68k.c (sched-int.h, insn-codes.h): New includes.
authormkuvyrkov <mkuvyrkov@138bc75d-0d04-0410-961f-82ee72b054a4>
Tue, 6 Nov 2007 16:52:17 +0000 (16:52 +0000)
committermkuvyrkov <mkuvyrkov@138bc75d-0d04-0410-961f-82ee72b054a4>
Tue, 6 Nov 2007 16:52:17 +0000 (16:52 +0000)
(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
gcc/config/m68k/cf.md [new file with mode: 0644]
gcc/config/m68k/m68k-protos.h
gcc/config/m68k/m68k.c
gcc/config/m68k/m68k.h
gcc/config/m68k/m68k.md

index 0025efa..96f7129 100644 (file)
@@ -1,3 +1,34 @@
+2007-11-06  Maxim Kuvyrkov  <maxim@codesourcery.com>
+
+       * 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  <tromey@redhat.com>
 
        PR c++/32256, PR c++/32368:
diff --git a/gcc/config/m68k/cf.md b/gcc/config/m68k/cf.md
new file mode 100644 (file)
index 0000000..b9c135c
--- /dev/null
@@ -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")
index 7d1ea97..bd03907 100644 (file)
@@ -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 */
index 952b947..142c8aa 100644 (file)
@@ -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 ();
+    }
+}
index c077c35..d8e1d3a 100644 (file)
@@ -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
index 68053b3..c3f3138 100644 (file)
   ""
   "#"
   [(set_attr "type" "ib")])
+
+(include "cf.md")