aboutsummaryrefslogtreecommitdiff
path: root/gcc/config/m68k
diff options
context:
space:
mode:
authorMaxim Kuvyrkov <maxim@codesourcery.com>2007-11-06 16:52:17 +0000
committerMaxim Kuvyrkov <mkuvyrkov@gcc.gnu.org>2007-11-06 16:52:17 +0000
commitb8c963204c1d408b202e17dd58ee56c5b8e27d30 (patch)
tree44ea9fcd381891e1ec3eb3d30c838056ea8895c2 /gcc/config/m68k
parent38d346765a731bd88dcda419cc2a247485f49507 (diff)
downloadgcc-b8c963204c1d408b202e17dd58ee56c5b8e27d30.zip
gcc-b8c963204c1d408b202e17dd58ee56c5b8e27d30.tar.gz
gcc-b8c963204c1d408b202e17dd58ee56c5b8e27d30.tar.bz2
m68k.c (sched-int.h, [...]): New includes.
* 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. From-SVN: r129938
Diffstat (limited to 'gcc/config/m68k')
-rw-r--r--gcc/config/m68k/cf.md679
-rw-r--r--gcc/config/m68k/m68k-protos.h1
-rw-r--r--gcc/config/m68k/m68k.c480
-rw-r--r--gcc/config/m68k/m68k.h1
-rw-r--r--gcc/config/m68k/m68k.md2
5 files changed, 1163 insertions, 0 deletions
diff --git a/gcc/config/m68k/cf.md b/gcc/config/m68k/cf.md
new file mode 100644
index 0000000..b9c135c
--- /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 7d1ea97..bd03907 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 952b947..142c8aa 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 c077c35..d8e1d3a 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 68053b3..c3f3138 100644
--- a/gcc/config/m68k/m68k.md
+++ b/gcc/config/m68k/m68k.md
@@ -7729,3 +7729,5 @@
""
"#"
[(set_attr "type" "ib")])
+
+(include "cf.md")