;; DFA-based pipeline description for MIPS32 models M5100.
;;
;; Copyright (C) 2015-2016 Free Software Foundation, 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 3, 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 COPYING3.  If not see
;; <http://www.gnu.org/licenses/>.

(define_automaton "m51_alu_pipe, m51_mdu_pipe, m51_fpu_pipe")
(define_cpu_unit "m51_mul" "m51_mdu_pipe")
(define_cpu_unit "m51_alu" "m51_alu_pipe")
(define_cpu_unit "m51_fpu" "m51_fpu_pipe")

;; --------------------------------------------------------------
;; ALU Instructions
;; --------------------------------------------------------------

;; ALU: Logicals
(define_insn_reservation "m51_int_logical" 1
  (and (eq_attr "cpu" "m5100")
       (eq_attr "type" "logical,move,signext,slt"))
  "m51_alu")

;; Arithmetics
(define_insn_reservation "m51_int" 1
  (and (eq_attr "cpu" "m5100")
       (eq_attr "type" "arith,const,shift,clz"))
  "m51_alu")

(define_insn_reservation "m51_int_nop" 0
  (and (eq_attr "cpu" "m5100")
       (eq_attr "type" "nop"))
  "nothing")

;; Conditional move
(define_insn_reservation "m51_int_cmove" 1
  (and (eq_attr "cpu" "m5100")
       (and (eq_attr "type" "condmove")
	    (eq_attr "mode" "SI,DI")))
  "m51_alu")

;; Call
(define_insn_reservation "m51_int_call" 1
  (and (eq_attr "cpu" "m5100")
       (eq_attr "type" "call"))
  "m51_alu")

;; branch/jump
(define_insn_reservation "m51_int_jump" 1
  (and (eq_attr "cpu" "m5100")
       (eq_attr "type" "branch,jump"))
  "m51_alu")

;; loads: lb, lbu, lh, lhu, ll, lw, lwl, lwr, lwpc, lwxs
;; prefetch: prefetch, prefetchx
(define_insn_reservation "m51_int_load" 3
  (and (eq_attr "cpu" "m5100")
       (eq_attr "type" "load,prefetch,prefetchx"))
  "m51_alu")

;; stores
(define_insn_reservation "m51_int_store" 1
  (and (eq_attr "cpu" "m5100")
       (eq_attr "type" "store"))
  "m51_alu")

;; --------------------------------------------------------------
;; MDU Instructions
;; --------------------------------------------------------------

;; High performance fully pipelined multiplier
;; MULT to HI/LO
(define_insn_reservation "m51_int_mult" 2
  (and (eq_attr "cpu" "m5100")
       (eq_attr "type" "imul,imadd"))
  "m51_alu+m51_mul*2")

;; MUL to GPR
(define_insn_reservation "m51_int_mul3" 2
  (and (eq_attr "cpu" "m5100")
       (eq_attr "type" "imul3"))
  "(m51_alu*2)+(m51_mul*2)")

;; mfhi, mflo
(define_insn_reservation "m51_int_mfhilo" 1
  (and (eq_attr "cpu" "m5100")
       (eq_attr "type" "mfhi,mflo"))
  "m51_mul")

;; mthi, mtlo
(define_insn_reservation "m51_int_mthilo" 1
  (and (eq_attr "cpu" "m5100")
       (eq_attr "type" "mthi,mtlo"))
  "m51_mul")

;; div
(define_insn_reservation "m51_int_div_si" 34
  (and (eq_attr "cpu" "m5100")
       (eq_attr "type" "idiv"))
  "m51_alu+m51_mul*34")

;; --------------------------------------------------------------
;; Floating Point Instructions
;; --------------------------------------------------------------

;; fadd, fabs, fneg
(define_insn_reservation "m51_fadd" 4
  (and (eq_attr "cpu" "m5100")
       (eq_attr "type" "fadd,fabs,fneg"))
  "m51_fpu")

;; fmove
(define_insn_reservation "m51_fmove" 4
  (and (eq_attr "cpu" "m5100")
       (eq_attr "type" "fmove"))
  "m51_fpu")

;; conditional move
(define_insn_reservation "m51_fp_cmove" 4
  (and (eq_attr "cpu" "m5100")
       (and (eq_attr "type" "condmove")
	    (eq_attr "mode" "SF,DF")))
  "m51_fpu")

;; fload
(define_insn_reservation "m51_fload" 3
  (and (eq_attr "cpu" "m5100")
       (eq_attr "type" "fpload,fpidxload"))
  "m51_fpu")

;; fstore
(define_insn_reservation "m51_fstore" 1
  (and (eq_attr "cpu" "m5100")
       (eq_attr "type" "fpstore,fpidxstore"))
  "m51_fpu")

;; fmul, fmadd
(define_insn_reservation "m51_fmul_sf" 4
  (and (eq_attr "cpu" "m5100")
       (and (eq_attr "type" "fmul,fmadd")
	    (eq_attr "mode" "SF")))
  "m51_fpu")

(define_insn_reservation "m51_fmul_df" 5
  (and (eq_attr "cpu" "m5100")
       (and (eq_attr "type" "fmul,fmadd")
	    (eq_attr "mode" "DF")))
  "m51_fpu*2")

;; fdiv, fsqrt
(define_insn_reservation "m51_fdiv_sf" 17
  (and (eq_attr "cpu" "m5100")
       (and (eq_attr "type" "fdiv,fsqrt")
	    (eq_attr "mode" "SF")))
  "m51_fpu*14")

(define_insn_reservation "m51_fdiv_df" 32
  (and (eq_attr "cpu" "m5100")
       (and (eq_attr "type" "fdiv,fsqrt")
	    (eq_attr "mode" "DF")))
  "m51_fpu*29")

;; frsqrt
(define_insn_reservation "m51_frsqrt_sf" 17
  (and (eq_attr "cpu" "m5100")
       (and (eq_attr "type" "frsqrt")
	    (eq_attr "mode" "SF")))
  "m51_fpu*14")

(define_insn_reservation "m51_frsqrt_df" 35
  (and (eq_attr "cpu" "m5100")
       (and (eq_attr "type" "frsqrt")
	    (eq_attr "mode" "DF")))
  "m51_fpu*31")

;; fcmp
(define_insn_reservation "m51_fcmp" 4
  (and (eq_attr "cpu" "m5100")
       (eq_attr "type" "fcmp"))
  "m51_fpu")

;; fcvt
;; cvt.s.d
(define_insn_reservation "m51_fcvt_6" 6
  (and (eq_attr "cpu" "m5100")
       (and (eq_attr "type" "fcvt")
	    (eq_attr "cnv_mode" "D2S")))
  "m51_fpu")

;; trunc
(define_insn_reservation "m51_fcvt_5" 5
  (and (eq_attr "cpu" "m5100")
       (and (eq_attr "type" "fcvt")
	    (eq_attr "cnv_mode" "D2I,S2I")))
  "m51_fpu")

;; cvt
(define_insn_reservation "m51_fcvt_4" 4
  (and (eq_attr "cpu" "m5100")
       (and (eq_attr "type" "fcvt")
	    (eq_attr "cnv_mode" "S2D,I2D,I2S")))
  "m51_fpu")

;; mtc, mfc
(define_insn_reservation "m51_move_to_from_c1" 2
  (and (eq_attr "cpu" "m5100")
       (eq_attr "type" "mtc, mfc"))
  "m51_fpu")
