;; Pipeline description for Motorola PowerPC e300c3 core. ;; Copyright (C) 2008-2022 Free Software Foundation, Inc. ;; Contributed by Edmar Wienskoski (edmar@freescale.com) ;; ;; 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 ;; . (define_automaton "ppce300c3_most,ppce300c3_long,ppce300c3_retire") (define_cpu_unit "ppce300c3_decode_0,ppce300c3_decode_1" "ppce300c3_most") ;; We don't simulate general issue queue (GIC). If we have SU insn ;; and then SU1 insn, they cannot be issued on the same cycle ;; (although SU1 insn and then SU insn can be issued) because the SU ;; insn will go to SU1 from GIC0 entry. Fortunately, the first cycle ;; multipass insn scheduling will find the situation and issue the SU1 ;; insn and then the SU insn. (define_cpu_unit "ppce300c3_issue_0,ppce300c3_issue_1" "ppce300c3_most") ;; We could describe completion buffers slots in combination with the ;; retirement units and the order of completion but the result ;; automaton would behave in the same way because we cannot describe ;; real latency time with taking in order completion into account. ;; Actually we could define the real latency time by querying reserved ;; automaton units but the current scheduler uses latency time before ;; issuing insns and making any reservations. ;; ;; So our description is aimed to achieve a insn schedule in which the ;; insns would not wait in the completion buffer. (define_cpu_unit "ppce300c3_retire_0,ppce300c3_retire_1" "ppce300c3_retire") ;; Branch unit: (define_cpu_unit "ppce300c3_bu" "ppce300c3_most") ;; IU: (define_cpu_unit "ppce300c3_iu0_stage0,ppce300c3_iu1_stage0" "ppce300c3_most") ;; IU: This used to describe non-pipelined division. (define_cpu_unit "ppce300c3_mu_div" "ppce300c3_long") ;; SRU: (define_cpu_unit "ppce300c3_sru_stage0" "ppce300c3_most") ;; Here we simplified LSU unit description not describing the stages. (define_cpu_unit "ppce300c3_lsu" "ppce300c3_most") ;; FPU: (define_cpu_unit "ppce300c3_fpu" "ppce300c3_most") ;; The following units are used to make automata deterministic (define_cpu_unit "present_ppce300c3_decode_0" "ppce300c3_most") (define_cpu_unit "present_ppce300c3_issue_0" "ppce300c3_most") (define_cpu_unit "present_ppce300c3_retire_0" "ppce300c3_retire") (define_cpu_unit "present_ppce300c3_iu0_stage0" "ppce300c3_most") ;; The following sets to make automata deterministic when option ndfa is used. (presence_set "present_ppce300c3_decode_0" "ppce300c3_decode_0") (presence_set "present_ppce300c3_issue_0" "ppce300c3_issue_0") (presence_set "present_ppce300c3_retire_0" "ppce300c3_retire_0") (presence_set "present_ppce300c3_iu0_stage0" "ppce300c3_iu0_stage0") ;; Some useful abbreviations. (define_reservation "ppce300c3_decode" "ppce300c3_decode_0|ppce300c3_decode_1+present_ppce300c3_decode_0") (define_reservation "ppce300c3_issue" "ppce300c3_issue_0|ppce300c3_issue_1+present_ppce300c3_issue_0") (define_reservation "ppce300c3_retire" "ppce300c3_retire_0|ppce300c3_retire_1+present_ppce300c3_retire_0") (define_reservation "ppce300c3_iu_stage0" "ppce300c3_iu0_stage0|ppce300c3_iu1_stage0+present_ppce300c3_iu0_stage0") ;; Compares can be executed either one of the IU or SRU (define_insn_reservation "ppce300c3_cmp" 1 (and (ior (eq_attr "type" "cmp") (and (eq_attr "type" "add,logical,shift,exts") (eq_attr "dot" "yes"))) (ior (eq_attr "cpu" "ppce300c2") (eq_attr "cpu" "ppce300c3"))) "ppce300c3_decode,ppce300c3_issue+(ppce300c3_iu_stage0|ppce300c3_sru_stage0) \ +ppce300c3_retire") ;; Other one cycle IU insns (define_insn_reservation "ppce300c3_iu" 1 (and (ior (eq_attr "type" "integer,insert,isel") (and (eq_attr "type" "add,logical,shift,exts") (eq_attr "dot" "no"))) (ior (eq_attr "cpu" "ppce300c2") (eq_attr "cpu" "ppce300c3"))) "ppce300c3_decode,ppce300c3_issue+ppce300c3_iu_stage0+ppce300c3_retire") ;; Branch. Actually this latency time is not used by the scheduler. (define_insn_reservation "ppce300c3_branch" 1 (and (eq_attr "type" "jmpreg,branch") (ior (eq_attr "cpu" "ppce300c2") (eq_attr "cpu" "ppce300c3"))) "ppce300c3_decode,ppce300c3_bu,ppce300c3_retire") ;; Multiply is non-pipelined but can be executed in any IU (define_insn_reservation "ppce300c3_multiply" 2 (and (eq_attr "type" "mul") (ior (eq_attr "cpu" "ppce300c2") (eq_attr "cpu" "ppce300c3"))) "ppce300c3_decode,ppce300c3_issue+ppce300c3_iu_stage0, \ ppce300c3_iu_stage0+ppce300c3_retire") ;; Divide. We use the average latency time here. We omit reserving a ;; retire unit because of the result automata will be huge. (define_insn_reservation "ppce300c3_divide" 20 (and (eq_attr "type" "div") (ior (eq_attr "cpu" "ppce300c2") (eq_attr "cpu" "ppce300c3"))) "ppce300c3_decode,ppce300c3_issue+ppce300c3_iu_stage0+ppce300c3_mu_div,\ ppce300c3_mu_div*19") ;; CR logical (define_insn_reservation "ppce300c3_cr_logical" 1 (and (eq_attr "type" "cr_logical") (ior (eq_attr "cpu" "ppce300c2") (eq_attr "cpu" "ppce300c3"))) "ppce300c3_decode,ppce300c3_issue+ppce300c3_sru_stage0+ppce300c3_retire") ;; Mfcr (define_insn_reservation "ppce300c3_mfcr" 1 (and (eq_attr "type" "mfcr") (ior (eq_attr "cpu" "ppce300c2") (eq_attr "cpu" "ppce300c3"))) "ppce300c3_decode,ppce300c3_issue+ppce300c3_sru_stage0+ppce300c3_retire") ;; Mtcrf (define_insn_reservation "ppce300c3_mtcrf" 1 (and (eq_attr "type" "mtcr") (ior (eq_attr "cpu" "ppce300c2") (eq_attr "cpu" "ppce300c3"))) "ppce300c3_decode,ppce300c3_issue+ppce300c3_sru_stage0+ppce300c3_retire") ;; Mtjmpr (define_insn_reservation "ppce300c3_mtjmpr" 1 (and (eq_attr "type" "mtjmpr,mfjmpr") (ior (eq_attr "cpu" "ppce300c2") (eq_attr "cpu" "ppce300c3"))) "ppce300c3_decode,ppce300c3_issue+ppce300c3_sru_stage0+ppce300c3_retire") ;; Float point instructions (define_insn_reservation "ppce300c3_fpcompare" 3 (and (eq_attr "type" "fpcompare") (eq_attr "cpu" "ppce300c3")) "ppce300c3_decode,ppce300c3_issue+ppce300c3_fpu,nothing,ppce300c3_retire") (define_insn_reservation "ppce300c3_fp" 3 (and (eq_attr "type" "fp,fpsimple") (eq_attr "cpu" "ppce300c3")) "ppce300c3_decode,ppce300c3_issue+ppce300c3_fpu,nothing,ppce300c3_retire") (define_insn_reservation "ppce300c3_dmul" 4 (and (eq_attr "type" "dmul") (eq_attr "cpu" "ppce300c3")) "ppce300c3_decode,ppce300c3_issue+ppce300c3_fpu,ppce300c3_fpu,nothing,ppce300c3_retire") ; Divides are not pipelined (define_insn_reservation "ppce300c3_sdiv" 18 (and (eq_attr "type" "sdiv") (eq_attr "cpu" "ppce300c3")) "ppce300c3_decode,ppce300c3_issue+ppce300c3_fpu,ppce300c3_fpu*17") (define_insn_reservation "ppce300c3_ddiv" 33 (and (eq_attr "type" "ddiv") (eq_attr "cpu" "ppce300c3")) "ppce300c3_decode,ppce300c3_issue+ppce300c3_fpu,ppce300c3_fpu*32") ;; Loads (define_insn_reservation "ppce300c3_load" 2 (and (eq_attr "type" "load") (ior (eq_attr "cpu" "ppce300c2") (eq_attr "cpu" "ppce300c3"))) "ppce300c3_decode,ppce300c3_issue+ppce300c3_lsu,ppce300c3_retire") (define_insn_reservation "ppce300c3_fpload" 2 (and (eq_attr "type" "fpload") (eq_attr "cpu" "ppce300c3")) "ppce300c3_decode,ppce300c3_issue+ppce300c3_lsu,ppce300c3_retire") ;; Stores. (define_insn_reservation "ppce300c3_store" 2 (and (eq_attr "type" "store") (ior (eq_attr "cpu" "ppce300c2") (eq_attr "cpu" "ppce300c3"))) "ppce300c3_decode,ppce300c3_issue+ppce300c3_lsu,ppce300c3_retire") (define_insn_reservation "ppce300c3_fpstore" 2 (and (eq_attr "type" "fpstore") (eq_attr "cpu" "ppce300c3")) "ppce300c3_decode,ppce300c3_issue+ppce300c3_lsu,ppce300c3_retire")