{RFA] PowerPC e500mc64 core support

View: New views
6 Messages — Rating Filter:   Alert me  

{RFA] PowerPC e500mc64 core support

by Edmar Wienskoski-RA8797-2 :: Rate this Message:

Reply to Author | View Threaded | Show Only this Message

Freescale would like to contribute this patch to gcc.

It enables gcc for the new Freescale 64 bit core. It creates a pipeline
description,
and set proper default flags for the e500mc64 core. It also create new
patterns for 64 bit
isel instruction generation.

The patch was generated from subversion revision 153598 from 2009-10-27

The patch was regression tested for both 603e and 970 targets under
these conditions:
--enable-checking --disable-decimal-float --enable-languages=c,c++,fortran

We thanks in advance for your time to review and commit the patch

Regards,
Edmar

2009-11-03  Edmar Wienskoski  edmar@...

        * config.gcc (cpu_is_64bit): Add new core e500mc64.
        (powerpc*-*-*): Add new core e500mc64.
        * config/rs6000/e500mc64.md: New file.
        * config/rs6000/rs6000.c (processor_costs): Add new costs for
        e500mc64.
        (rs6000_override_options): Add e500mc64 case to
        processor_target_table. Altivec and Spe options not allowed with
        e500mc64. Disable string instructions for e500mc64. Enable branch
        targets alignment for both e500mc and e500mc64. Initialize
        rs6000_cost for e500mc64.
        (rs6000_emit_sISEL): New function.
        (rs6000_emit_int_cmove): Fix mode of 64 bit isel pattern
        generation.
        (rs6000_issue_rate): Set issue rate for e500mc64.
        (rs6000_rtx_costs): Set more accurate cost for mfcr instruction
        on architectures with isel.
        * config/rs6000/rs6000-protos.h: Declare new function.
        * config/rs6000/rs6000.h (processor_type): Add
        PROCESSOR_PPCE500MC64.
        (ASM_CPU_SPEC): Add e500mc64.
        Define TARGET_E500MC64.
        * config/rs6000/rs6000.md (define_attr "cpu"): Add ppce500mc64.
        Include e500mc64.md.
        (abssi2_isel): Expand pattern to handle DImode.
        (nabs<mode>2_isel): New pattern.
        (floatdidf2): Add e500mc64
        (floatdidf2_fpr): Ditto.
        (fix_truncdfdi2): Ditto.
        (fix_truncdfdi2_fpr): Ditto.
        (absdi2): Change pattern to handle 64 bit isel targets.
        (absdi2_internal): Exclude isel targets.
        (nabsdi2): Exclude isel targets.
        (cstore<mode>4): Call rs6000_emit_sISEL for isel targets.
        * doc/invoke.texi: Add e500mc64 to list of cpus.

2009-11-03  Edmar Wienskoski  edmar@...

        * gcc.target/powerpc/ppc-eq0-1.c: Adjust testcase for isel
        targets.

diff -ruN gcc-4.5-20091027/gcc/config/rs6000/e500mc64.md gcc-4.5-e500mc64-20091027/gcc/config/rs6000/e500mc64.md
--- gcc-4.5-20091027/gcc/config/rs6000/e500mc64.md 1969-12-31 18:00:00.000000000 -0600
+++ gcc-4.5-e500mc64-20091027/gcc/config/rs6000/e500mc64.md 2009-10-27 11:00:02.000000000 -0500
@@ -0,0 +1,186 @@
+;; Pipeline description for Motorola PowerPC e500mc64 core.
+;;   Copyright (C) 2009 Free Software Foundation, Inc.
+;;   Contributed by Edmar Wienskoski (edmar@...)
+;;
+;; 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/>.
+;;
+;; e500mc64 64-bit SU(2), LSU, FPU, BPU
+;; Max issue 3 insns/clock cycle (includes 1 branch)
+
+(define_automaton "e500mc64_most,e500mc64_long,e500mc64_retire")
+(define_cpu_unit "e500mc64_decode_0,e500mc64_decode_1" "e500mc64_most")
+(define_cpu_unit "e500mc64_issue_0,e500mc64_issue_1"   "e500mc64_most")
+(define_cpu_unit "e500mc64_retire_0,e500mc64_retire_1" "e500mc64_retire")
+
+;; SU.
+(define_cpu_unit "e500mc64_su0_stage0,e500mc64_su1_stage0" "e500mc64_most")
+
+;; MU.
+(define_cpu_unit "e500mc64_mu_stage0,e500mc64_mu_stage1" "e500mc64_most")
+(define_cpu_unit "e500mc64_mu_stage2,e500mc64_mu_stage3" "e500mc64_most")
+
+;; Non-pipelined division.
+(define_cpu_unit "e500mc64_mu_div" "e500mc64_long")
+
+;; LSU.
+(define_cpu_unit "e500mc64_lsu" "e500mc64_most")
+
+;; FPU.
+(define_cpu_unit "e500mc64_fpu" "e500mc64_most")
+
+;; Branch unit.
+(define_cpu_unit "e500mc64_bu" "e500mc64_most")
+
+;; The following units are used to make the automata deterministic.
+(define_cpu_unit "present_e500mc64_decode_0" "e500mc64_most")
+(define_cpu_unit "present_e500mc64_issue_0" "e500mc64_most")
+(define_cpu_unit "present_e500mc64_retire_0" "e500mc64_retire")
+(define_cpu_unit "present_e500mc64_su0_stage0" "e500mc64_most")
+
+;; The following sets to make automata deterministic when option ndfa is used.
+(presence_set "present_e500mc64_decode_0" "e500mc64_decode_0")
+(presence_set "present_e500mc64_issue_0" "e500mc64_issue_0")
+(presence_set "present_e500mc64_retire_0" "e500mc64_retire_0")
+(presence_set "present_e500mc64_su0_stage0" "e500mc64_su0_stage0")
+
+;; Some useful abbreviations.
+(define_reservation "e500mc64_decode"
+    "e500mc64_decode_0|e500mc64_decode_1+present_e500mc64_decode_0")
+(define_reservation "e500mc64_issue"
+    "e500mc64_issue_0|e500mc64_issue_1+present_e500mc64_issue_0")
+(define_reservation "e500mc64_retire"
+   "e500mc64_retire_0|e500mc64_retire_1+present_e500mc64_retire_0")
+(define_reservation "e500mc64_su_stage0"
+   "e500mc64_su0_stage0|e500mc64_su1_stage0+present_e500mc64_su0_stage0")
+
+;; Simple SU insns.
+(define_insn_reservation "e500mc64_su" 1
+  (and (eq_attr "type" "integer,insert_word,insert_dword,cmp,compare,\
+                        delayed_compare,fast_compare,shift,trap,cntlz,exts")
+       (eq_attr "cpu" "ppce500mc64"))
+  "e500mc64_decode,e500mc64_issue+e500mc64_su_stage0+e500mc64_retire")
+
+(define_insn_reservation "e500mc64_delayed" 2
+  (and (eq_attr "type" "var_shift_rotate,var_delayed_compare")
+       (eq_attr "cpu" "ppce500mc64"))
+  "e500mc64_decode,e500mc64_issue+e500mc64_su_stage0,e500mc64_retire")
+
+(define_insn_reservation "e500mc64_two" 2
+  (and (eq_attr "type" "two")
+       (eq_attr "cpu" "ppce500mc64"))
+  "e500mc64_decode,e500mc64_issue+e500mc64_su_stage0+e500mc64_retire,\
+   e500mc64_issue+e500mc64_su_stage0+e500mc64_retire")
+
+(define_insn_reservation "e500mc64_three" 3
+  (and (eq_attr "type" "three")
+       (eq_attr "cpu" "ppce500mc64"))
+  "e500mc64_decode,e500mc64_issue+e500mc64_su_stage0+e500mc64_retire,\
+   e500mc64_issue+e500mc64_su_stage0+e500mc64_retire,\
+   e500mc64_issue+e500mc64_su_stage0+e500mc64_retire")
+
+;; Multiply.
+(define_insn_reservation "e500mc64_multiply" 4
+  (and (eq_attr "type" "imul,imul2,imul3,imul_compare")
+       (eq_attr "cpu" "ppce500mc64"))
+  "e500mc64_decode,e500mc64_issue+e500mc64_mu_stage0,e500mc64_mu_stage1,\
+   e500mc64_mu_stage2,e500mc64_mu_stage3+e500mc64_retire")
+
+;; Divide. We use the average latency time here.
+(define_insn_reservation "e500mc64_divide" 14
+  (and (eq_attr "type" "idiv")
+       (eq_attr "cpu" "ppce500mc64"))
+  "e500mc64_decode,e500mc64_issue+e500mc64_mu_stage0+e500mc64_mu_div,\
+   e500mc64_mu_div*13")
+
+;; Branch.
+(define_insn_reservation "e500mc64_branch" 1
+  (and (eq_attr "type" "jmpreg,branch,isync")
+       (eq_attr "cpu" "ppce500mc64"))
+  "e500mc64_decode,e500mc64_bu,e500mc64_retire")
+
+;; CR logical.
+(define_insn_reservation "e500mc64_cr_logical" 1
+  (and (eq_attr "type" "cr_logical,delayed_cr")
+       (eq_attr "cpu" "ppce500mc64"))
+  "e500mc64_decode,e500mc64_bu,e500mc64_retire")
+
+;; Mfcr.
+(define_insn_reservation "e500mc64_mfcr" 4
+  (and (eq_attr "type" "mfcr")
+       (eq_attr "cpu" "ppce500mc64"))
+  "e500mc64_decode,e500mc64_issue+e500mc64_su1_stage0,e500mc64_su1_stage0*3+e500mc64_retire")
+
+;; Mtcrf.
+(define_insn_reservation "e500mc64_mtcrf" 1
+  (and (eq_attr "type" "mtcr")
+       (eq_attr "cpu" "ppce500mc64"))
+  "e500mc64_decode,e500mc64_issue+e500mc64_su1_stage0+e500mc64_retire")
+
+;; Mtjmpr.
+(define_insn_reservation "e500mc64_mtjmpr" 1
+  (and (eq_attr "type" "mtjmpr,mfjmpr")
+       (eq_attr "cpu" "ppce500mc64"))
+  "e500mc64_decode,e500mc64_issue+e500mc64_su_stage0+e500mc64_retire")
+
+;; Brinc.
+(define_insn_reservation "e500mc64_brinc" 1
+  (and (eq_attr "type" "brinc")
+       (eq_attr "cpu" "ppce500mc64"))
+  "e500mc64_decode,e500mc64_issue+e500mc64_su_stage0+e500mc64_retire")
+
+;; Loads.
+(define_insn_reservation "e500mc64_load" 3
+  (and (eq_attr "type" "load,load_ext,load_ext_u,load_ext_ux,load_ux,load_u,\
+ load_l,sync")
+       (eq_attr "cpu" "ppce500mc64"))
+  "e500mc64_decode,e500mc64_issue+e500mc64_lsu,nothing,e500mc64_retire")
+
+(define_insn_reservation "e500mc64_fpload" 4
+  (and (eq_attr "type" "fpload,fpload_ux,fpload_u")
+       (eq_attr "cpu" "ppce500mc64"))
+  "e500mc64_decode,e500mc64_issue+e500mc64_lsu,nothing*2,e500mc64_retire")
+
+;; Stores.
+(define_insn_reservation "e500mc64_store" 3
+  (and (eq_attr "type" "store,store_ux,store_u,store_c")
+       (eq_attr "cpu" "ppce500mc64"))
+  "e500mc64_decode,e500mc64_issue+e500mc64_lsu,nothing,e500mc64_retire")
+
+(define_insn_reservation "e500mc64_fpstore" 3
+  (and (eq_attr "type" "fpstore,fpstore_ux,fpstore_u")
+       (eq_attr "cpu" "ppce500mc64"))
+  "e500mc64_decode,e500mc64_issue+e500mc64_lsu,nothing,e500mc64_retire")
+
+;; The following ignores the retire unit to avoid a large automata.
+
+;; FP.
+(define_insn_reservation "e500mc64_float" 7
+  (and (eq_attr "type" "fpsimple,fp,fpcompare,dmul")
+       (eq_attr "cpu" "ppce500mc64"))
+  "e500mc64_decode,e500mc64_issue+e500mc64_fpu")
+; "e500mc64_decode,e500mc64_issue+e500mc64_fpu,nothing*5,e500mc64_retire")
+
+;; FP divides are not pipelined.
+(define_insn_reservation "e500mc64_sdiv" 20
+  (and (eq_attr "type" "sdiv")
+       (eq_attr "cpu" "ppce500mc64"))
+  "e500mc64_decode,e500mc64_issue+e500mc64_fpu,e500mc64_fpu*19")
+
+(define_insn_reservation "e500mc64_ddiv" 35
+  (and (eq_attr "type" "ddiv")
+       (eq_attr "cpu" "ppce500mc64"))
+  "e500mc64_decode,e500mc64_issue+e500mc64_fpu,e500mc64_fpu*34")
diff -ruN gcc-4.5-20091027/gcc/config/rs6000/rs6000.c gcc-4.5-e500mc64-20091027/gcc/config/rs6000/rs6000.c
--- gcc-4.5-20091027/gcc/config/rs6000/rs6000.c 2009-10-27 10:49:12.000000000 -0500
+++ gcc-4.5-e500mc64-20091027/gcc/config/rs6000/rs6000.c 2009-10-27 11:00:02.000000000 -0500
@@ -761,6 +761,25 @@
   1, /* prefetch streams /*/
 };
 
+/* Instruction costs on PPCE500MC64 processors.  */
+static const
+struct processor_costs ppce500mc64_cost = {
+  COSTS_N_INSNS (4),    /* mulsi */
+  COSTS_N_INSNS (4),    /* mulsi_const */
+  COSTS_N_INSNS (4),    /* mulsi_const9 */
+  COSTS_N_INSNS (4),    /* muldi */
+  COSTS_N_INSNS (14),   /* divsi */
+  COSTS_N_INSNS (14),   /* divdi */
+  COSTS_N_INSNS (4),    /* fp */
+  COSTS_N_INSNS (10),   /* dmul */
+  COSTS_N_INSNS (36),   /* sdiv */
+  COSTS_N_INSNS (66),   /* ddiv */
+  64, /* cache line size */
+  32, /* l1 cache */
+  128, /* l2 cache */
+  1, /* prefetch streams /*/
+};
+
 /* Instruction costs on POWER4 and POWER5 processors.  */
 static const
 struct processor_costs power4_cost = {
@@ -2217,6 +2236,8 @@
  {"e300c3", PROCESSOR_PPCE300C3, POWERPC_BASE_MASK},
  {"e500mc", PROCESSOR_PPCE500MC, POWERPC_BASE_MASK | MASK_PPC_GFXOPT
   | MASK_ISEL},
+ {"e500mc64", PROCESSOR_PPCE500MC64,
+  POWERPC_BASE_MASK | MASK_PPC_GFXOPT | MASK_POWERPC64 | MASK_ISEL},
  {"860", PROCESSOR_MPCCORE, POWERPC_BASE_MASK | MASK_SOFT_FLOAT},
  {"970", PROCESSOR_POWER4,
   POWERPC_7400_MASK | MASK_PPC_GPOPT | MASK_MFCRF | MASK_POWERPC64},
@@ -2345,7 +2366,7 @@
     }
 
   if (rs6000_cpu == PROCESSOR_PPCE300C2 || rs6000_cpu == PROCESSOR_PPCE300C3
-      || rs6000_cpu == PROCESSOR_PPCE500MC)
+      || rs6000_cpu == PROCESSOR_PPCE500MC || TARGET_E500MC64)
     {
       if (TARGET_ALTIVEC)
  error ("AltiVec not supported in this target");
@@ -2537,7 +2558,7 @@
   SUB3TARGET_OVERRIDE_OPTIONS;
 #endif
 
-  if (TARGET_E500 || rs6000_cpu == PROCESSOR_PPCE500MC)
+  if (TARGET_E500 || rs6000_cpu == PROCESSOR_PPCE500MC || TARGET_E500MC64)
     {
       /* The e500 and e500mc do not have string instructions, and we set
  MASK_STRING above when optimizing for size.  */
@@ -2574,7 +2595,9 @@
   rs6000_align_branch_targets = (rs6000_cpu == PROCESSOR_POWER4
  || rs6000_cpu == PROCESSOR_POWER5
  || rs6000_cpu == PROCESSOR_POWER6
- || rs6000_cpu == PROCESSOR_POWER7);
+ || rs6000_cpu == PROCESSOR_POWER7
+ || rs6000_cpu == PROCESSOR_PPCE500MC
+                                 || rs6000_cpu == PROCESSOR_PPCE500MC64);
 
   /* Allow debug switches to override the above settings.  */
   if (TARGET_ALWAYS_HINT > 0)
@@ -2776,6 +2799,10 @@
  rs6000_cost = &ppce500mc_cost;
  break;
 
+      case PROCESSOR_PPCE500MC64:
+ rs6000_cost = &ppce500mc64_cost;
+ break;
+
       case PROCESSOR_POWER4:
       case PROCESSOR_POWER5:
  rs6000_cost = &power4_cost;
@@ -15433,6 +15460,53 @@
 /* Emit the RTL for an sCOND pattern.  */
 
 void
+rs6000_emit_sISEL (enum machine_mode mode, rtx operands[])
+{
+  rtx condition_rtx;
+  enum machine_mode op_mode;
+  enum rtx_code cond_code;
+  rtx result = operands[0];
+
+  condition_rtx = rs6000_generate_compare (operands[1], mode);
+  cond_code = GET_CODE (condition_rtx);
+
+  op_mode = GET_MODE (XEXP (operands[1], 0));
+  if (op_mode == VOIDmode)
+    op_mode = GET_MODE (XEXP (operands[1], 1));
+
+  if (TARGET_POWERPC64 && GET_MODE (result) == DImode)
+    {
+      PUT_MODE (condition_rtx, DImode);
+      if (cond_code == GEU || cond_code == GTU || cond_code == LEU
+         || cond_code == LTU)
+       emit_insn (gen_isel_unsigned_di (result, condition_rtx,
+                                        force_reg (DImode, const1_rtx),
+                                        force_reg (DImode, const0_rtx),
+                                        XEXP (condition_rtx, 0)));
+      else
+       emit_insn (gen_isel_signed_di (result, condition_rtx,
+                                      force_reg (DImode, const1_rtx),
+                                      force_reg (DImode, const0_rtx),
+                                      XEXP (condition_rtx, 0)));
+    }
+  else
+    {
+      PUT_MODE (condition_rtx, SImode);
+      if (cond_code == GEU || cond_code == GTU || cond_code == LEU
+         || cond_code == LTU)
+       emit_insn (gen_isel_unsigned_si (result, condition_rtx,
+                                        force_reg (SImode, const1_rtx),
+                                        force_reg (SImode, const0_rtx),
+ XEXP (condition_rtx, 0)));
+      else
+       emit_insn (gen_isel_signed_si (result, condition_rtx,
+      force_reg (SImode, const1_rtx),
+      force_reg (SImode, const0_rtx),
+      XEXP (condition_rtx, 0)));
+    }
+}
+
+void
 rs6000_emit_sCOND (enum machine_mode mode, rtx operands[])
 {
   rtx condition_rtx;
@@ -16089,7 +16163,7 @@
 rs6000_emit_int_cmove (rtx dest, rtx op, rtx true_cond, rtx false_cond)
 {
   rtx condition_rtx, cr;
-  enum machine_mode mode = GET_MODE (XEXP (op, 0));
+  enum machine_mode mode = GET_MODE (dest);
 
   if (mode != SImode && (!TARGET_POWERPC64 || mode != DImode))
     return 0;
@@ -16097,7 +16171,7 @@
   /* We still have to do the compare, because isel doesn't do a
      compare, it just looks at the CRx bits set by a previous compare
      instruction.  */
-  condition_rtx = rs6000_generate_compare (op, SImode);
+  condition_rtx = rs6000_generate_compare (op, mode);
   cr = XEXP (condition_rtx, 0);
 
   if (mode == SImode)
@@ -21952,6 +22026,7 @@
   case CPU_PPCE300C2:
   case CPU_PPCE300C3:
   case CPU_PPCE500MC:
+  case CPU_PPCE500MC64:
     return 2;
   case CPU_RIOS2:
   case CPU_PPC476:
@@ -24765,7 +24840,10 @@
  {
   if (XEXP (x, 1) == const0_rtx)
     {
-      *total = COSTS_N_INSNS (2);
+      if (TARGET_ISEL)
+ *total = COSTS_N_INSNS (8);
+      else
+ *total = COSTS_N_INSNS (2);
       return true;
     }
   else if (mode == Pmode)
@@ -24781,7 +24859,10 @@
     case UNORDERED:
       if (outer_code == SET && (XEXP (x, 1) == const0_rtx))
  {
-  *total = COSTS_N_INSNS (2);
+  if (TARGET_ISEL)
+    *total = COSTS_N_INSNS (8);
+  else
+    *total = COSTS_N_INSNS (2);
   return true;
  }
       /* CC COMPARE.  */
diff -ruN gcc-4.5-20091027/gcc/config/rs6000/rs6000.h gcc-4.5-e500mc64-20091027/gcc/config/rs6000/rs6000.h
--- gcc-4.5-20091027/gcc/config/rs6000/rs6000.h 2009-10-27 10:49:12.000000000 -0500
+++ gcc-4.5-e500mc64-20091027/gcc/config/rs6000/rs6000.h 2009-10-27 11:00:02.000000000 -0500
@@ -158,6 +158,7 @@
 %{mcpu=e300c2: -me300} \
 %{mcpu=e300c3: -me300} \
 %{mcpu=e500mc: -me500mc} \
+%{mcpu=e500mc64: -me500mc64} \
 %{maltivec: -maltivec} \
 -many"
 
@@ -341,6 +342,7 @@
    PROCESSOR_PPCE300C2,
    PROCESSOR_PPCE300C3,
    PROCESSOR_PPCE500MC,
+   PROCESSOR_PPCE500MC64,
    PROCESSOR_POWER4,
    PROCESSOR_POWER5,
    PROCESSOR_POWER6,
@@ -536,6 +538,7 @@
 #define TARGET_FPRS 1
 #define TARGET_E500_SINGLE 0
 #define TARGET_E500_DOUBLE 0
+#define TARGET_E500MC64 (rs6000_cpu == PROCESSOR_PPCE500MC64)
 #define CHECK_E500_OPTIONS do { } while (0)
 
 /* E500 processors only support plain "sync", not lwsync.  */
diff -ruN gcc-4.5-20091027/gcc/config/rs6000/rs6000.md gcc-4.5-e500mc64-20091027/gcc/config/rs6000/rs6000.md
--- gcc-4.5-20091027/gcc/config/rs6000/rs6000.md 2009-10-27 10:49:12.000000000 -0500
+++ gcc-4.5-e500mc64-20091027/gcc/config/rs6000/rs6000.md 2009-11-03 10:35:06.000000000 -0600
@@ -139,7 +139,7 @@
 ;; Processor type -- this attribute must exactly match the processor_type
 ;; enumeration in rs6000.h.
 
-(define_attr "cpu" "rios1,rios2,rs64a,mpccore,ppc403,ppc405,ppc440,ppc476,ppc601,ppc603,ppc604,ppc604e,ppc620,ppc630,ppc750,ppc7400,ppc7450,ppc8540,ppce300c2,ppce300c3,ppce500mc,power4,power5,power6,power7,cell,ppca2"
+(define_attr "cpu" "rios1,rios2,rs64a,mpccore,ppc403,ppc405,ppc440,ppc476,ppc601,ppc603,ppc604,ppc604e,ppc620,ppc630,ppc750,ppc7400,ppc7450,ppc8540,ppce300c2,ppce300c3,ppce500mc,ppce500mc64,power4,power5,power6,power7,cell,ppca2"
   (const (symbol_ref "rs6000_cpu_attr")))
 
 
@@ -166,6 +166,7 @@
 (include "8540.md")
 (include "e300c2c3.md")
 (include "e500mc.md")
+(include "e500mc64.md")
 (include "power4.md")
 (include "power5.md")
 (include "power6.md")
@@ -2077,23 +2078,42 @@
   "TARGET_POWER"
   "abs %0,%1")
 
-(define_insn_and_split "abssi2_isel"
-  [(set (match_operand:SI 0 "gpc_reg_operand" "=r")
-        (abs:SI (match_operand:SI 1 "gpc_reg_operand" "b")))
-   (clobber (match_scratch:SI 2 "=&b"))
+(define_insn_and_split "abs<mode>2_isel"
+  [(set (match_operand:GPR 0 "gpc_reg_operand" "=r")
+        (abs:GPR (match_operand:GPR 1 "gpc_reg_operand" "b")))
+   (clobber (match_scratch:GPR 2 "=&b"))
    (clobber (match_scratch:CC 3 "=y"))]
   "TARGET_ISEL"
   "#"
   "&& reload_completed"
-  [(set (match_dup 2) (neg:SI (match_dup 1)))
+  [(set (match_dup 2) (neg:GPR (match_dup 1)))
    (set (match_dup 3)
  (compare:CC (match_dup 1)
     (const_int 0)))
    (set (match_dup 0)
- (if_then_else:SI (ge (match_dup 3)
-     (const_int 0))
- (match_dup 1)
- (match_dup 2)))]
+ (if_then_else:GPR (ge (match_dup 3)
+      (const_int 0))
+  (match_dup 1)
+  (match_dup 2)))]
+  "")
+
+(define_insn_and_split "nabs<mode>2_isel"
+  [(set (match_operand:GPR 0 "gpc_reg_operand" "=r")
+        (neg:GPR (abs:GPR (match_operand:GPR 1 "gpc_reg_operand" "b"))))
+   (clobber (match_scratch:GPR 2 "=&b"))
+   (clobber (match_scratch:CC 3 "=y"))]
+  "TARGET_ISEL"
+  "#"
+  "&& reload_completed"
+  [(set (match_dup 2) (neg:GPR (match_dup 1)))
+   (set (match_dup 3)
+ (compare:CC (match_dup 1)
+    (const_int 0)))
+   (set (match_dup 0)
+ (if_then_else:GPR (ge (match_dup 3)
+      (const_int 0))
+  (match_dup 2)
+  (match_dup 1)))]
   "")
 
 (define_insn_and_split "abssi2_nopower"
@@ -6738,14 +6758,15 @@
 (define_expand "floatdidf2"
   [(set (match_operand:DF 0 "gpc_reg_operand" "")
  (float:DF (match_operand:DI 1 "gpc_reg_operand" "")))]
-  "(TARGET_POWERPC64 || TARGET_XILINX_FPU || VECTOR_UNIT_VSX_P (DFmode))
+  "(TARGET_POWERPC64 || TARGET_XILINX_FPU || VECTOR_UNIT_VSX_P (DFmode)
+    || TARGET_E500MC64)
    && TARGET_HARD_FLOAT && TARGET_DOUBLE_FLOAT && TARGET_FPRS"
   "")
 
 (define_insn "*floatdidf2_fpr"
   [(set (match_operand:DF 0 "gpc_reg_operand" "=d")
  (float:DF (match_operand:DI 1 "gpc_reg_operand" "!d#r")))]
-  "(TARGET_POWERPC64 || TARGET_XILINX_FPU)
+  "(TARGET_POWERPC64 || TARGET_XILINX_FPU || TARGET_E500MC64)
    && TARGET_HARD_FLOAT && TARGET_DOUBLE_FLOAT && TARGET_FPRS
    && !VECTOR_UNIT_VSX_P (DFmode)"
   "fcfid %0,%1"
@@ -6760,14 +6781,15 @@
 (define_expand "fix_truncdfdi2"
   [(set (match_operand:DI 0 "gpc_reg_operand" "")
  (fix:DI (match_operand:DF 1 "gpc_reg_operand" "")))]
-  "(TARGET_POWERPC64 || TARGET_XILINX_FPU || VECTOR_UNIT_VSX_P (DFmode))
+  "(TARGET_POWERPC64 || TARGET_XILINX_FPU || VECTOR_UNIT_VSX_P (DFmode)
+    || TARGET_E500MC64)
     && TARGET_HARD_FLOAT && TARGET_DOUBLE_FLOAT && TARGET_FPRS"
   "")
 
 (define_insn "*fix_truncdfdi2_fpr"
   [(set (match_operand:DI 0 "gpc_reg_operand" "=!d#r")
  (fix:DI (match_operand:DF 1 "gpc_reg_operand" "d")))]
-  "(TARGET_POWERPC64 || TARGET_XILINX_FPU) && TARGET_HARD_FLOAT
+  "(TARGET_POWERPC64 || TARGET_XILINX_FPU || TARGET_E500MC64) && TARGET_HARD_FLOAT
     && TARGET_DOUBLE_FLOAT && TARGET_FPRS && !VECTOR_UNIT_VSX_P (DFmode)"
   "fctidz %0,%1"
   [(set_attr "type" "fp")])
@@ -7197,11 +7219,24 @@
 
 ;; PowerPC64 DImode operations.
 
-(define_insn_and_split "absdi2"
+(define_expand "absdi2"
+  [(set (match_operand:DI 0 "gpc_reg_operand" "")
+ (abs:DI (match_operand:DI 1 "gpc_reg_operand" "")))]
+  "TARGET_POWERPC64"
+  "
+{
+  if (TARGET_ISEL)
+    emit_insn (gen_absdi2_isel (operands[0], operands[1]));
+  else
+    emit_insn (gen_absdi2_internal (operands[0], operands[1]));
+  DONE;
+}")
+
+(define_insn_and_split "absdi2_internal"
   [(set (match_operand:DI 0 "gpc_reg_operand" "=&r,r")
         (abs:DI (match_operand:DI 1 "gpc_reg_operand" "r,0")))
    (clobber (match_scratch:DI 2 "=&r,&r"))]
-  "TARGET_POWERPC64"
+  "TARGET_POWERPC64 && !TARGET_ISEL"
   "#"
   "&& reload_completed"
   [(set (match_dup 2) (ashiftrt:DI (match_dup 1) (const_int 63)))
@@ -7213,7 +7248,7 @@
   [(set (match_operand:DI 0 "gpc_reg_operand" "=&r,r")
         (neg:DI (abs:DI (match_operand:DI 1 "gpc_reg_operand" "r,0"))))
    (clobber (match_scratch:DI 2 "=&r,&r"))]
-  "TARGET_POWERPC64"
+  "TARGET_POWERPC64 && !TARGET_ISEL"
   "#"
   "&& reload_completed"
   [(set (match_dup 2) (ashiftrt:DI (match_dup 1) (const_int 63)))
@@ -12588,7 +12623,10 @@
        || GET_CODE (operands[1]) == GT || GET_CODE (operands[1]) == GE)
       && operands[3] == const0_rtx)
     FAIL;
-  rs6000_emit_sCOND (<MODE>mode, operands);
+  if (TARGET_ISEL<sel>)
+    rs6000_emit_sISEL (<MODE>mode, operands);
+  else
+    rs6000_emit_sCOND (<MODE>mode, operands);
   DONE;
 }")
 
diff -ruN gcc-4.5-20091027/gcc/config/rs6000/rs6000-protos.h gcc-4.5-e500mc64-20091027/gcc/config/rs6000/rs6000-protos.h
--- gcc-4.5-20091027/gcc/config/rs6000/rs6000-protos.h 2009-10-27 10:49:12.000000000 -0500
+++ gcc-4.5-e500mc64-20091027/gcc/config/rs6000/rs6000-protos.h 2009-10-27 11:00:02.000000000 -0500
@@ -90,6 +90,7 @@
 extern bool rs6000_output_addr_const_extra (FILE *, rtx);
 extern enum rtx_code rs6000_reverse_condition (enum machine_mode,
        enum rtx_code);
+extern void rs6000_emit_sISEL (enum machine_mode, rtx[]);
 extern void rs6000_emit_sCOND (enum machine_mode, rtx[]);
 extern void rs6000_emit_cbranch (enum machine_mode, rtx[]);
 extern char * output_cbranch (rtx, const char *, int, rtx);
diff -ruN gcc-4.5-20091027/gcc/config.gcc gcc-4.5-e500mc64-20091027/gcc/config.gcc
--- gcc-4.5-20091027/gcc/config.gcc 2009-10-27 10:49:28.000000000 -0500
+++ gcc-4.5-e500mc64-20091027/gcc/config.gcc 2009-10-27 11:00:40.000000000 -0500
@@ -327,7 +327,7 @@
  extra_headers="ppc-asm.h altivec.h spe.h ppu_intrinsics.h paired.h spu2vmx.h vec_types.h si2vmx.h"
  need_64bit_hwint=yes
  case x$with_cpu in
-    xpowerpc64|xdefault64|x6[23]0|x970|xG5|xpower[34567]|xpower6x|xrs64a|xcell|xa2)
+    xpowerpc64|xdefault64|x6[23]0|x970|xG5|xpower[34567]|xpower6x|xrs64a|xcell|xa2|xe500mc64)
  cpu_is_64bit=yes
  ;;
  esac
@@ -3072,7 +3072,7 @@
  | 401 | 403 | 405 | 405fp | 440 | 440fp | 464 | 464fp \
  | 476 | 476fp | 505 | 601 | 602 | 603 | 603e | ec603e \
  | 604 | 604e | 620 | 630 | 740 | 750 | 7400 | 7450 \
- | a2 | e300c[23] | 854[08] | e500mc \
+ | a2 | e300c[23] | 854[08] | e500mc | e500mc64 \
  | 801 | 821 | 823 | 860 | 970 | G3 | G4 | G5 | cell)
  # OK
  ;;
diff -ruN gcc-4.5-20091027/gcc/doc/invoke.texi gcc-4.5-e500mc64-20091027/gcc/doc/invoke.texi
--- gcc-4.5-20091027/gcc/doc/invoke.texi 2009-10-27 10:42:17.000000000 -0500
+++ gcc-4.5-e500mc64-20091027/gcc/doc/invoke.texi 2009-11-03 12:52:17.000000000 -0600
@@ -14656,10 +14656,10 @@
 @samp{603e}, @samp{604}, @samp{604e}, @samp{620}, @samp{630}, @samp{740},
 @samp{7400}, @samp{7450}, @samp{750}, @samp{801}, @samp{821}, @samp{823},
 @samp{860}, @samp{970}, @samp{8540}, @samp{a2}, @samp{e300c2},
-@samp{e300c3}, @samp{e500mc}, @samp{ec603e}, @samp{G3}, @samp{G4}, @samp{G5},
-@samp{power}, @samp{power2}, @samp{power3}, @samp{power4},
-@samp{power5}, @samp{power5+}, @samp{power6}, @samp{power6x}, @samp{power7},
-@samp{common}, @samp{powerpc}, @samp{powerpc64}, @samp{rios},
+@samp{e300c3}, @samp{e500mc}, @samp{e500mc64}, @samp{ec603e}, @samp{G3},
+@samp{G4}, @samp{G5}, @samp{power}, @samp{power2}, @samp{power3},
+@samp{power4}, @samp{power5}, @samp{power5+}, @samp{power6}, @samp{power6x},
+@samp{power7}, @samp{common}, @samp{powerpc}, @samp{powerpc64}, @samp{rios},
 @samp{rios1}, @samp{rios2}, @samp{rsc}, and @samp{rs64}.
 
 @option{-mcpu=common} selects a completely generic processor.  Code
diff -ruN gcc-4.5-20091027/gcc/testsuite/gcc.target/powerpc/ppc-eq0-1.c gcc-4.5-e500mc64-20091027/gcc/testsuite/gcc.target/powerpc/ppc-eq0-1.c
--- gcc-4.5-20091027/gcc/testsuite/gcc.target/powerpc/ppc-eq0-1.c 2009-10-27 10:42:56.000000000 -0500
+++ gcc-4.5-e500mc64-20091027/gcc/testsuite/gcc.target/powerpc/ppc-eq0-1.c 2009-11-03 10:35:53.000000000 -0600
@@ -7,4 +7,4 @@
   return x == 0;
 }
 
-/* { dg-final { scan-assembler "cntlzw" } } */
+/* { dg-final { scan-assembler "cntlzw|isel" } } */

Parent Message unknown Re: {RFA] PowerPC e500mc64 core support

by David Edelsohn-3 :: Rate this Message:

Reply to Author | View Threaded | Show Only this Message

Edmar,

Creating TARGET_E500MC64 is incorrect, the macro should represent a
feature, not a processor.  The rs6000.c tests should use
PROCESSOR_E500MC64.

The change to floatdidf2 pattern does not make sense because it
already tests TARGET_POWERPC64 and e500mc64 sets MASK_POWERPC64,
similarly for the other di/df patterns.

I do not see any useful purpose for TARGET_E500MC64.

Should rs6000_emit_sCOND() call rs6000_emit_sISEL() instead of
modifying cstore<mode>4 ?

Thanks, David

Re: {RFA] PowerPC e500mc64 core support

by Edmar Wienskoski-RA8797-2 :: Rate this Message:

Reply to Author | View Threaded | Show Only this Message

David Edelsohn wrote:

> Edmar,
>
> Creating TARGET_E500MC64 is incorrect, the macro should represent a
> feature, not a processor.  The rs6000.c tests should use
> PROCESSOR_E500MC64.
>
> The change to floatdidf2 pattern does not make sense because it
> already tests TARGET_POWERPC64 and e500mc64 sets MASK_POWERPC64,
> similarly for the other di/df patterns.
>
> I do not see any useful purpose for TARGET_E500MC64.
>
> Should rs6000_emit_sCOND() call rs6000_emit_sISEL() instead of
> modifying cstore<mode>4 ?
>
> Thanks, David
>
>
>  
Hi David.

I updated the patches with the changes. I also updated the Changelog
to reflect that the floatdidf2 changes are intended for 32 bits as well.

Regards,

Edmar



2009-11-03  Edmar Wienskoski  edmar@...

        * config.gcc (cpu_is_64bit): Add new core e500mc64.
        (powerpc*-*-*): Add new core e500mc64.
        * config/rs6000/e500mc64.md: New file.
        * config/rs6000/rs6000.c (processor_costs): Add new costs for
        e500mc64.
        (rs6000_override_options): Add e500mc64 case to
        processor_target_table. Altivec and Spe options not allowed with
        e500mc64. Disable string instructions for e500mc64. Enable branch
        targets alignment for both e500mc and e500mc64. Initialize
        rs6000_cost for e500mc64.
        (rs6000_emit_sISEL): New function.
        (rs6000_emit_sCOND): Call rs6000_emit_sISEL for isel targets.
        (rs6000_emit_int_cmove): Fix mode of 64 bit isel pattern
        generation.
        (rs6000_issue_rate): Set issue rate for e500mc64.
        (rs6000_rtx_costs): Set more accurate cost for mfcr instruction
        on architectures with isel.
        * config/rs6000/rs6000-protos.h: Declare new function.
        * config/rs6000/rs6000.h (processor_type): Add
        PROCESSOR_PPCE500MC64.
        (ASM_CPU_SPEC): Add e500mc64.
        * config/rs6000/rs6000.md (define_attr "cpu"): Add ppce500mc64.
        Include e500mc64.md.
        (abssi2_isel): Expand pattern to handle DImode.
        (nabs<mode>2_isel): New pattern.
        (floatdidf2): Add e500mc64 for both 32bits and 64bits mode.
        (floatdidf2_fpr): Ditto.
        (fix_truncdfdi2): Ditto.
        (fix_truncdfdi2_fpr): Ditto.
        (absdi2): Change pattern to handle 64 bit isel targets.
        (absdi2_internal): Exclude isel targets.
        (nabsdi2): Exclude isel targets.
        * doc/invoke.texi: Add e500mc64 to list of cpus.

2009-11-03  Edmar Wienskoski  edmar@...

        * gcc.target/powerpc/ppc-eq0-1.c: Adjust testcase for isel
        targets.

diff -ruN gcc-4.5-20091027/gcc/config/rs6000/e500mc64.md gcc-4.5-e500mc64-20091027/gcc/config/rs6000/e500mc64.md
--- gcc-4.5-20091027/gcc/config/rs6000/e500mc64.md 1969-12-31 18:00:00.000000000 -0600
+++ gcc-4.5-e500mc64-20091027/gcc/config/rs6000/e500mc64.md 2009-10-27 11:00:02.000000000 -0500
@@ -0,0 +1,186 @@
+;; Pipeline description for Motorola PowerPC e500mc64 core.
+;;   Copyright (C) 2009 Free Software Foundation, Inc.
+;;   Contributed by Edmar Wienskoski (edmar@...)
+;;
+;; 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/>.
+;;
+;; e500mc64 64-bit SU(2), LSU, FPU, BPU
+;; Max issue 3 insns/clock cycle (includes 1 branch)
+
+(define_automaton "e500mc64_most,e500mc64_long,e500mc64_retire")
+(define_cpu_unit "e500mc64_decode_0,e500mc64_decode_1" "e500mc64_most")
+(define_cpu_unit "e500mc64_issue_0,e500mc64_issue_1"   "e500mc64_most")
+(define_cpu_unit "e500mc64_retire_0,e500mc64_retire_1" "e500mc64_retire")
+
+;; SU.
+(define_cpu_unit "e500mc64_su0_stage0,e500mc64_su1_stage0" "e500mc64_most")
+
+;; MU.
+(define_cpu_unit "e500mc64_mu_stage0,e500mc64_mu_stage1" "e500mc64_most")
+(define_cpu_unit "e500mc64_mu_stage2,e500mc64_mu_stage3" "e500mc64_most")
+
+;; Non-pipelined division.
+(define_cpu_unit "e500mc64_mu_div" "e500mc64_long")
+
+;; LSU.
+(define_cpu_unit "e500mc64_lsu" "e500mc64_most")
+
+;; FPU.
+(define_cpu_unit "e500mc64_fpu" "e500mc64_most")
+
+;; Branch unit.
+(define_cpu_unit "e500mc64_bu" "e500mc64_most")
+
+;; The following units are used to make the automata deterministic.
+(define_cpu_unit "present_e500mc64_decode_0" "e500mc64_most")
+(define_cpu_unit "present_e500mc64_issue_0" "e500mc64_most")
+(define_cpu_unit "present_e500mc64_retire_0" "e500mc64_retire")
+(define_cpu_unit "present_e500mc64_su0_stage0" "e500mc64_most")
+
+;; The following sets to make automata deterministic when option ndfa is used.
+(presence_set "present_e500mc64_decode_0" "e500mc64_decode_0")
+(presence_set "present_e500mc64_issue_0" "e500mc64_issue_0")
+(presence_set "present_e500mc64_retire_0" "e500mc64_retire_0")
+(presence_set "present_e500mc64_su0_stage0" "e500mc64_su0_stage0")
+
+;; Some useful abbreviations.
+(define_reservation "e500mc64_decode"
+    "e500mc64_decode_0|e500mc64_decode_1+present_e500mc64_decode_0")
+(define_reservation "e500mc64_issue"
+    "e500mc64_issue_0|e500mc64_issue_1+present_e500mc64_issue_0")
+(define_reservation "e500mc64_retire"
+   "e500mc64_retire_0|e500mc64_retire_1+present_e500mc64_retire_0")
+(define_reservation "e500mc64_su_stage0"
+   "e500mc64_su0_stage0|e500mc64_su1_stage0+present_e500mc64_su0_stage0")
+
+;; Simple SU insns.
+(define_insn_reservation "e500mc64_su" 1
+  (and (eq_attr "type" "integer,insert_word,insert_dword,cmp,compare,\
+                        delayed_compare,fast_compare,shift,trap,cntlz,exts")
+       (eq_attr "cpu" "ppce500mc64"))
+  "e500mc64_decode,e500mc64_issue+e500mc64_su_stage0+e500mc64_retire")
+
+(define_insn_reservation "e500mc64_delayed" 2
+  (and (eq_attr "type" "var_shift_rotate,var_delayed_compare")
+       (eq_attr "cpu" "ppce500mc64"))
+  "e500mc64_decode,e500mc64_issue+e500mc64_su_stage0,e500mc64_retire")
+
+(define_insn_reservation "e500mc64_two" 2
+  (and (eq_attr "type" "two")
+       (eq_attr "cpu" "ppce500mc64"))
+  "e500mc64_decode,e500mc64_issue+e500mc64_su_stage0+e500mc64_retire,\
+   e500mc64_issue+e500mc64_su_stage0+e500mc64_retire")
+
+(define_insn_reservation "e500mc64_three" 3
+  (and (eq_attr "type" "three")
+       (eq_attr "cpu" "ppce500mc64"))
+  "e500mc64_decode,e500mc64_issue+e500mc64_su_stage0+e500mc64_retire,\
+   e500mc64_issue+e500mc64_su_stage0+e500mc64_retire,\
+   e500mc64_issue+e500mc64_su_stage0+e500mc64_retire")
+
+;; Multiply.
+(define_insn_reservation "e500mc64_multiply" 4
+  (and (eq_attr "type" "imul,imul2,imul3,imul_compare")
+       (eq_attr "cpu" "ppce500mc64"))
+  "e500mc64_decode,e500mc64_issue+e500mc64_mu_stage0,e500mc64_mu_stage1,\
+   e500mc64_mu_stage2,e500mc64_mu_stage3+e500mc64_retire")
+
+;; Divide. We use the average latency time here.
+(define_insn_reservation "e500mc64_divide" 14
+  (and (eq_attr "type" "idiv")
+       (eq_attr "cpu" "ppce500mc64"))
+  "e500mc64_decode,e500mc64_issue+e500mc64_mu_stage0+e500mc64_mu_div,\
+   e500mc64_mu_div*13")
+
+;; Branch.
+(define_insn_reservation "e500mc64_branch" 1
+  (and (eq_attr "type" "jmpreg,branch,isync")
+       (eq_attr "cpu" "ppce500mc64"))
+  "e500mc64_decode,e500mc64_bu,e500mc64_retire")
+
+;; CR logical.
+(define_insn_reservation "e500mc64_cr_logical" 1
+  (and (eq_attr "type" "cr_logical,delayed_cr")
+       (eq_attr "cpu" "ppce500mc64"))
+  "e500mc64_decode,e500mc64_bu,e500mc64_retire")
+
+;; Mfcr.
+(define_insn_reservation "e500mc64_mfcr" 4
+  (and (eq_attr "type" "mfcr")
+       (eq_attr "cpu" "ppce500mc64"))
+  "e500mc64_decode,e500mc64_issue+e500mc64_su1_stage0,e500mc64_su1_stage0*3+e500mc64_retire")
+
+;; Mtcrf.
+(define_insn_reservation "e500mc64_mtcrf" 1
+  (and (eq_attr "type" "mtcr")
+       (eq_attr "cpu" "ppce500mc64"))
+  "e500mc64_decode,e500mc64_issue+e500mc64_su1_stage0+e500mc64_retire")
+
+;; Mtjmpr.
+(define_insn_reservation "e500mc64_mtjmpr" 1
+  (and (eq_attr "type" "mtjmpr,mfjmpr")
+       (eq_attr "cpu" "ppce500mc64"))
+  "e500mc64_decode,e500mc64_issue+e500mc64_su_stage0+e500mc64_retire")
+
+;; Brinc.
+(define_insn_reservation "e500mc64_brinc" 1
+  (and (eq_attr "type" "brinc")
+       (eq_attr "cpu" "ppce500mc64"))
+  "e500mc64_decode,e500mc64_issue+e500mc64_su_stage0+e500mc64_retire")
+
+;; Loads.
+(define_insn_reservation "e500mc64_load" 3
+  (and (eq_attr "type" "load,load_ext,load_ext_u,load_ext_ux,load_ux,load_u,\
+ load_l,sync")
+       (eq_attr "cpu" "ppce500mc64"))
+  "e500mc64_decode,e500mc64_issue+e500mc64_lsu,nothing,e500mc64_retire")
+
+(define_insn_reservation "e500mc64_fpload" 4
+  (and (eq_attr "type" "fpload,fpload_ux,fpload_u")
+       (eq_attr "cpu" "ppce500mc64"))
+  "e500mc64_decode,e500mc64_issue+e500mc64_lsu,nothing*2,e500mc64_retire")
+
+;; Stores.
+(define_insn_reservation "e500mc64_store" 3
+  (and (eq_attr "type" "store,store_ux,store_u,store_c")
+       (eq_attr "cpu" "ppce500mc64"))
+  "e500mc64_decode,e500mc64_issue+e500mc64_lsu,nothing,e500mc64_retire")
+
+(define_insn_reservation "e500mc64_fpstore" 3
+  (and (eq_attr "type" "fpstore,fpstore_ux,fpstore_u")
+       (eq_attr "cpu" "ppce500mc64"))
+  "e500mc64_decode,e500mc64_issue+e500mc64_lsu,nothing,e500mc64_retire")
+
+;; The following ignores the retire unit to avoid a large automata.
+
+;; FP.
+(define_insn_reservation "e500mc64_float" 7
+  (and (eq_attr "type" "fpsimple,fp,fpcompare,dmul")
+       (eq_attr "cpu" "ppce500mc64"))
+  "e500mc64_decode,e500mc64_issue+e500mc64_fpu")
+; "e500mc64_decode,e500mc64_issue+e500mc64_fpu,nothing*5,e500mc64_retire")
+
+;; FP divides are not pipelined.
+(define_insn_reservation "e500mc64_sdiv" 20
+  (and (eq_attr "type" "sdiv")
+       (eq_attr "cpu" "ppce500mc64"))
+  "e500mc64_decode,e500mc64_issue+e500mc64_fpu,e500mc64_fpu*19")
+
+(define_insn_reservation "e500mc64_ddiv" 35
+  (and (eq_attr "type" "ddiv")
+       (eq_attr "cpu" "ppce500mc64"))
+  "e500mc64_decode,e500mc64_issue+e500mc64_fpu,e500mc64_fpu*34")
diff -ruN gcc-4.5-20091027/gcc/config/rs6000/rs6000.c gcc-4.5-e500mc64-20091027/gcc/config/rs6000/rs6000.c
--- gcc-4.5-20091027/gcc/config/rs6000/rs6000.c 2009-10-27 10:49:12.000000000 -0500
+++ gcc-4.5-e500mc64-20091027/gcc/config/rs6000/rs6000.c 2009-11-04 12:44:23.000000000 -0600
@@ -761,6 +761,25 @@
   1, /* prefetch streams /*/
 };
 
+/* Instruction costs on PPCE500MC64 processors.  */
+static const
+struct processor_costs ppce500mc64_cost = {
+  COSTS_N_INSNS (4),    /* mulsi */
+  COSTS_N_INSNS (4),    /* mulsi_const */
+  COSTS_N_INSNS (4),    /* mulsi_const9 */
+  COSTS_N_INSNS (4),    /* muldi */
+  COSTS_N_INSNS (14),   /* divsi */
+  COSTS_N_INSNS (14),   /* divdi */
+  COSTS_N_INSNS (4),    /* fp */
+  COSTS_N_INSNS (10),   /* dmul */
+  COSTS_N_INSNS (36),   /* sdiv */
+  COSTS_N_INSNS (66),   /* ddiv */
+  64, /* cache line size */
+  32, /* l1 cache */
+  128, /* l2 cache */
+  1, /* prefetch streams /*/
+};
+
 /* Instruction costs on POWER4 and POWER5 processors.  */
 static const
 struct processor_costs power4_cost = {
@@ -2217,6 +2236,8 @@
  {"e300c3", PROCESSOR_PPCE300C3, POWERPC_BASE_MASK},
  {"e500mc", PROCESSOR_PPCE500MC, POWERPC_BASE_MASK | MASK_PPC_GFXOPT
   | MASK_ISEL},
+ {"e500mc64", PROCESSOR_PPCE500MC64,
+  POWERPC_BASE_MASK | MASK_PPC_GFXOPT | MASK_POWERPC64 | MASK_ISEL},
  {"860", PROCESSOR_MPCCORE, POWERPC_BASE_MASK | MASK_SOFT_FLOAT},
  {"970", PROCESSOR_POWER4,
   POWERPC_7400_MASK | MASK_PPC_GPOPT | MASK_MFCRF | MASK_POWERPC64},
@@ -2345,7 +2366,7 @@
     }
 
   if (rs6000_cpu == PROCESSOR_PPCE300C2 || rs6000_cpu == PROCESSOR_PPCE300C3
-      || rs6000_cpu == PROCESSOR_PPCE500MC)
+      || rs6000_cpu == PROCESSOR_PPCE500MC || rs6000_cpu == PROCESSOR_PPCE500MC64)
     {
       if (TARGET_ALTIVEC)
  error ("AltiVec not supported in this target");
@@ -2537,7 +2558,8 @@
   SUB3TARGET_OVERRIDE_OPTIONS;
 #endif
 
-  if (TARGET_E500 || rs6000_cpu == PROCESSOR_PPCE500MC)
+  if (TARGET_E500 || rs6000_cpu == PROCESSOR_PPCE500MC
+      || rs6000_cpu == PROCESSOR_PPCE500MC64)
     {
       /* The e500 and e500mc do not have string instructions, and we set
  MASK_STRING above when optimizing for size.  */
@@ -2574,7 +2596,9 @@
   rs6000_align_branch_targets = (rs6000_cpu == PROCESSOR_POWER4
  || rs6000_cpu == PROCESSOR_POWER5
  || rs6000_cpu == PROCESSOR_POWER6
- || rs6000_cpu == PROCESSOR_POWER7);
+ || rs6000_cpu == PROCESSOR_POWER7
+ || rs6000_cpu == PROCESSOR_PPCE500MC
+                                 || rs6000_cpu == PROCESSOR_PPCE500MC64);
 
   /* Allow debug switches to override the above settings.  */
   if (TARGET_ALWAYS_HINT > 0)
@@ -2776,6 +2800,10 @@
  rs6000_cost = &ppce500mc_cost;
  break;
 
+      case PROCESSOR_PPCE500MC64:
+ rs6000_cost = &ppce500mc64_cost;
+ break;
+
       case PROCESSOR_POWER4:
       case PROCESSOR_POWER5:
  rs6000_cost = &power4_cost;
@@ -15433,6 +15461,53 @@
 /* Emit the RTL for an sCOND pattern.  */
 
 void
+rs6000_emit_sISEL (enum machine_mode mode, rtx operands[])
+{
+  rtx condition_rtx;
+  enum machine_mode op_mode;
+  enum rtx_code cond_code;
+  rtx result = operands[0];
+
+  condition_rtx = rs6000_generate_compare (operands[1], mode);
+  cond_code = GET_CODE (condition_rtx);
+
+  op_mode = GET_MODE (XEXP (operands[1], 0));
+  if (op_mode == VOIDmode)
+    op_mode = GET_MODE (XEXP (operands[1], 1));
+
+  if (TARGET_POWERPC64 && GET_MODE (result) == DImode)
+    {
+      PUT_MODE (condition_rtx, DImode);
+      if (cond_code == GEU || cond_code == GTU || cond_code == LEU
+         || cond_code == LTU)
+       emit_insn (gen_isel_unsigned_di (result, condition_rtx,
+                                        force_reg (DImode, const1_rtx),
+                                        force_reg (DImode, const0_rtx),
+                                        XEXP (condition_rtx, 0)));
+      else
+       emit_insn (gen_isel_signed_di (result, condition_rtx,
+                                      force_reg (DImode, const1_rtx),
+                                      force_reg (DImode, const0_rtx),
+                                      XEXP (condition_rtx, 0)));
+    }
+  else
+    {
+      PUT_MODE (condition_rtx, SImode);
+      if (cond_code == GEU || cond_code == GTU || cond_code == LEU
+         || cond_code == LTU)
+       emit_insn (gen_isel_unsigned_si (result, condition_rtx,
+                                        force_reg (SImode, const1_rtx),
+                                        force_reg (SImode, const0_rtx),
+ XEXP (condition_rtx, 0)));
+      else
+       emit_insn (gen_isel_signed_si (result, condition_rtx,
+      force_reg (SImode, const1_rtx),
+      force_reg (SImode, const0_rtx),
+      XEXP (condition_rtx, 0)));
+    }
+}
+
+void
 rs6000_emit_sCOND (enum machine_mode mode, rtx operands[])
 {
   rtx condition_rtx;
@@ -15440,6 +15515,12 @@
   enum rtx_code cond_code;
   rtx result = operands[0];
 
+  if (TARGET_ISEL && (mode == SImode || mode == DImode))
+    {
+      rs6000_emit_sISEL (mode, operands);
+      return;
+    }
+
   condition_rtx = rs6000_generate_compare (operands[1], mode);
   cond_code = GET_CODE (condition_rtx);
 
@@ -16089,7 +16170,7 @@
 rs6000_emit_int_cmove (rtx dest, rtx op, rtx true_cond, rtx false_cond)
 {
   rtx condition_rtx, cr;
-  enum machine_mode mode = GET_MODE (XEXP (op, 0));
+  enum machine_mode mode = GET_MODE (dest);
 
   if (mode != SImode && (!TARGET_POWERPC64 || mode != DImode))
     return 0;
@@ -16097,7 +16178,7 @@
   /* We still have to do the compare, because isel doesn't do a
      compare, it just looks at the CRx bits set by a previous compare
      instruction.  */
-  condition_rtx = rs6000_generate_compare (op, SImode);
+  condition_rtx = rs6000_generate_compare (op, mode);
   cr = XEXP (condition_rtx, 0);
 
   if (mode == SImode)
@@ -21952,6 +22033,7 @@
   case CPU_PPCE300C2:
   case CPU_PPCE300C3:
   case CPU_PPCE500MC:
+  case CPU_PPCE500MC64:
     return 2;
   case CPU_RIOS2:
   case CPU_PPC476:
@@ -24765,7 +24847,10 @@
  {
   if (XEXP (x, 1) == const0_rtx)
     {
-      *total = COSTS_N_INSNS (2);
+      if (TARGET_ISEL)
+ *total = COSTS_N_INSNS (8);
+      else
+ *total = COSTS_N_INSNS (2);
       return true;
     }
   else if (mode == Pmode)
@@ -24781,7 +24866,10 @@
     case UNORDERED:
       if (outer_code == SET && (XEXP (x, 1) == const0_rtx))
  {
-  *total = COSTS_N_INSNS (2);
+  if (TARGET_ISEL)
+    *total = COSTS_N_INSNS (8);
+  else
+    *total = COSTS_N_INSNS (2);
   return true;
  }
       /* CC COMPARE.  */
diff -ruN gcc-4.5-20091027/gcc/config/rs6000/rs6000.h gcc-4.5-e500mc64-20091027/gcc/config/rs6000/rs6000.h
--- gcc-4.5-20091027/gcc/config/rs6000/rs6000.h 2009-10-27 10:49:12.000000000 -0500
+++ gcc-4.5-e500mc64-20091027/gcc/config/rs6000/rs6000.h 2009-11-04 10:34:41.000000000 -0600
@@ -158,6 +158,7 @@
 %{mcpu=e300c2: -me300} \
 %{mcpu=e300c3: -me300} \
 %{mcpu=e500mc: -me500mc} \
+%{mcpu=e500mc64: -me500mc64} \
 %{maltivec: -maltivec} \
 -many"
 
@@ -341,6 +342,7 @@
    PROCESSOR_PPCE300C2,
    PROCESSOR_PPCE300C3,
    PROCESSOR_PPCE500MC,
+   PROCESSOR_PPCE500MC64,
    PROCESSOR_POWER4,
    PROCESSOR_POWER5,
    PROCESSOR_POWER6,
diff -ruN gcc-4.5-20091027/gcc/config/rs6000/rs6000.md gcc-4.5-e500mc64-20091027/gcc/config/rs6000/rs6000.md
--- gcc-4.5-20091027/gcc/config/rs6000/rs6000.md 2009-10-27 10:49:12.000000000 -0500
+++ gcc-4.5-e500mc64-20091027/gcc/config/rs6000/rs6000.md 2009-11-04 10:38:07.000000000 -0600
@@ -139,7 +139,7 @@
 ;; Processor type -- this attribute must exactly match the processor_type
 ;; enumeration in rs6000.h.
 
-(define_attr "cpu" "rios1,rios2,rs64a,mpccore,ppc403,ppc405,ppc440,ppc476,ppc601,ppc603,ppc604,ppc604e,ppc620,ppc630,ppc750,ppc7400,ppc7450,ppc8540,ppce300c2,ppce300c3,ppce500mc,power4,power5,power6,power7,cell,ppca2"
+(define_attr "cpu" "rios1,rios2,rs64a,mpccore,ppc403,ppc405,ppc440,ppc476,ppc601,ppc603,ppc604,ppc604e,ppc620,ppc630,ppc750,ppc7400,ppc7450,ppc8540,ppce300c2,ppce300c3,ppce500mc,ppce500mc64,power4,power5,power6,power7,cell,ppca2"
   (const (symbol_ref "rs6000_cpu_attr")))
 
 
@@ -166,6 +166,7 @@
 (include "8540.md")
 (include "e300c2c3.md")
 (include "e500mc.md")
+(include "e500mc64.md")
 (include "power4.md")
 (include "power5.md")
 (include "power6.md")
@@ -2077,23 +2078,42 @@
   "TARGET_POWER"
   "abs %0,%1")
 
-(define_insn_and_split "abssi2_isel"
-  [(set (match_operand:SI 0 "gpc_reg_operand" "=r")
-        (abs:SI (match_operand:SI 1 "gpc_reg_operand" "b")))
-   (clobber (match_scratch:SI 2 "=&b"))
+(define_insn_and_split "abs<mode>2_isel"
+  [(set (match_operand:GPR 0 "gpc_reg_operand" "=r")
+        (abs:GPR (match_operand:GPR 1 "gpc_reg_operand" "b")))
+   (clobber (match_scratch:GPR 2 "=&b"))
    (clobber (match_scratch:CC 3 "=y"))]
   "TARGET_ISEL"
   "#"
   "&& reload_completed"
-  [(set (match_dup 2) (neg:SI (match_dup 1)))
+  [(set (match_dup 2) (neg:GPR (match_dup 1)))
    (set (match_dup 3)
  (compare:CC (match_dup 1)
     (const_int 0)))
    (set (match_dup 0)
- (if_then_else:SI (ge (match_dup 3)
-     (const_int 0))
- (match_dup 1)
- (match_dup 2)))]
+ (if_then_else:GPR (ge (match_dup 3)
+      (const_int 0))
+  (match_dup 1)
+  (match_dup 2)))]
+  "")
+
+(define_insn_and_split "nabs<mode>2_isel"
+  [(set (match_operand:GPR 0 "gpc_reg_operand" "=r")
+        (neg:GPR (abs:GPR (match_operand:GPR 1 "gpc_reg_operand" "b"))))
+   (clobber (match_scratch:GPR 2 "=&b"))
+   (clobber (match_scratch:CC 3 "=y"))]
+  "TARGET_ISEL"
+  "#"
+  "&& reload_completed"
+  [(set (match_dup 2) (neg:GPR (match_dup 1)))
+   (set (match_dup 3)
+ (compare:CC (match_dup 1)
+    (const_int 0)))
+   (set (match_dup 0)
+ (if_then_else:GPR (ge (match_dup 3)
+      (const_int 0))
+  (match_dup 2)
+  (match_dup 1)))]
   "")
 
 (define_insn_and_split "abssi2_nopower"
@@ -6738,14 +6758,15 @@
 (define_expand "floatdidf2"
   [(set (match_operand:DF 0 "gpc_reg_operand" "")
  (float:DF (match_operand:DI 1 "gpc_reg_operand" "")))]
-  "(TARGET_POWERPC64 || TARGET_XILINX_FPU || VECTOR_UNIT_VSX_P (DFmode))
+  "(TARGET_POWERPC64 || TARGET_XILINX_FPU || VECTOR_UNIT_VSX_P (DFmode)
+    || rs6000_cpu == PROCESSOR_PPCE500MC64)
    && TARGET_HARD_FLOAT && TARGET_DOUBLE_FLOAT && TARGET_FPRS"
   "")
 
 (define_insn "*floatdidf2_fpr"
   [(set (match_operand:DF 0 "gpc_reg_operand" "=d")
  (float:DF (match_operand:DI 1 "gpc_reg_operand" "!d#r")))]
-  "(TARGET_POWERPC64 || TARGET_XILINX_FPU)
+  "(TARGET_POWERPC64 || TARGET_XILINX_FPU || rs6000_cpu == PROCESSOR_PPCE500MC64)
    && TARGET_HARD_FLOAT && TARGET_DOUBLE_FLOAT && TARGET_FPRS
    && !VECTOR_UNIT_VSX_P (DFmode)"
   "fcfid %0,%1"
@@ -6760,15 +6781,17 @@
 (define_expand "fix_truncdfdi2"
   [(set (match_operand:DI 0 "gpc_reg_operand" "")
  (fix:DI (match_operand:DF 1 "gpc_reg_operand" "")))]
-  "(TARGET_POWERPC64 || TARGET_XILINX_FPU || VECTOR_UNIT_VSX_P (DFmode))
+  "(TARGET_POWERPC64 || TARGET_XILINX_FPU || VECTOR_UNIT_VSX_P (DFmode)
+    || rs6000_cpu == PROCESSOR_PPCE500MC64)
     && TARGET_HARD_FLOAT && TARGET_DOUBLE_FLOAT && TARGET_FPRS"
   "")
 
 (define_insn "*fix_truncdfdi2_fpr"
   [(set (match_operand:DI 0 "gpc_reg_operand" "=!d#r")
  (fix:DI (match_operand:DF 1 "gpc_reg_operand" "d")))]
-  "(TARGET_POWERPC64 || TARGET_XILINX_FPU) && TARGET_HARD_FLOAT
-    && TARGET_DOUBLE_FLOAT && TARGET_FPRS && !VECTOR_UNIT_VSX_P (DFmode)"
+  "(TARGET_POWERPC64 || TARGET_XILINX_FPU || rs6000_cpu == PROCESSOR_PPCE500MC64)
+    && TARGET_HARD_FLOAT && TARGET_DOUBLE_FLOAT && TARGET_FPRS
+    && !VECTOR_UNIT_VSX_P (DFmode)"
   "fctidz %0,%1"
   [(set_attr "type" "fp")])
 
@@ -7197,11 +7220,24 @@
 
 ;; PowerPC64 DImode operations.
 
-(define_insn_and_split "absdi2"
+(define_expand "absdi2"
+  [(set (match_operand:DI 0 "gpc_reg_operand" "")
+ (abs:DI (match_operand:DI 1 "gpc_reg_operand" "")))]
+  "TARGET_POWERPC64"
+  "
+{
+  if (TARGET_ISEL)
+    emit_insn (gen_absdi2_isel (operands[0], operands[1]));
+  else
+    emit_insn (gen_absdi2_internal (operands[0], operands[1]));
+  DONE;
+}")
+
+(define_insn_and_split "absdi2_internal"
   [(set (match_operand:DI 0 "gpc_reg_operand" "=&r,r")
         (abs:DI (match_operand:DI 1 "gpc_reg_operand" "r,0")))
    (clobber (match_scratch:DI 2 "=&r,&r"))]
-  "TARGET_POWERPC64"
+  "TARGET_POWERPC64 && !TARGET_ISEL"
   "#"
   "&& reload_completed"
   [(set (match_dup 2) (ashiftrt:DI (match_dup 1) (const_int 63)))
@@ -7213,7 +7249,7 @@
   [(set (match_operand:DI 0 "gpc_reg_operand" "=&r,r")
         (neg:DI (abs:DI (match_operand:DI 1 "gpc_reg_operand" "r,0"))))
    (clobber (match_scratch:DI 2 "=&r,&r"))]
-  "TARGET_POWERPC64"
+  "TARGET_POWERPC64 && !TARGET_ISEL"
   "#"
   "&& reload_completed"
   [(set (match_dup 2) (ashiftrt:DI (match_dup 1) (const_int 63)))
diff -ruN gcc-4.5-20091027/gcc/config/rs6000/rs6000-protos.h gcc-4.5-e500mc64-20091027/gcc/config/rs6000/rs6000-protos.h
--- gcc-4.5-20091027/gcc/config/rs6000/rs6000-protos.h 2009-10-27 10:49:12.000000000 -0500
+++ gcc-4.5-e500mc64-20091027/gcc/config/rs6000/rs6000-protos.h 2009-10-27 11:00:02.000000000 -0500
@@ -90,6 +90,7 @@
 extern bool rs6000_output_addr_const_extra (FILE *, rtx);
 extern enum rtx_code rs6000_reverse_condition (enum machine_mode,
        enum rtx_code);
+extern void rs6000_emit_sISEL (enum machine_mode, rtx[]);
 extern void rs6000_emit_sCOND (enum machine_mode, rtx[]);
 extern void rs6000_emit_cbranch (enum machine_mode, rtx[]);
 extern char * output_cbranch (rtx, const char *, int, rtx);
diff -ruN gcc-4.5-20091027/gcc/config.gcc gcc-4.5-e500mc64-20091027/gcc/config.gcc
--- gcc-4.5-20091027/gcc/config.gcc 2009-10-27 10:49:28.000000000 -0500
+++ gcc-4.5-e500mc64-20091027/gcc/config.gcc 2009-10-27 11:00:40.000000000 -0500
@@ -327,7 +327,7 @@
  extra_headers="ppc-asm.h altivec.h spe.h ppu_intrinsics.h paired.h spu2vmx.h vec_types.h si2vmx.h"
  need_64bit_hwint=yes
  case x$with_cpu in
-    xpowerpc64|xdefault64|x6[23]0|x970|xG5|xpower[34567]|xpower6x|xrs64a|xcell|xa2)
+    xpowerpc64|xdefault64|x6[23]0|x970|xG5|xpower[34567]|xpower6x|xrs64a|xcell|xa2|xe500mc64)
  cpu_is_64bit=yes
  ;;
  esac
@@ -3072,7 +3072,7 @@
  | 401 | 403 | 405 | 405fp | 440 | 440fp | 464 | 464fp \
  | 476 | 476fp | 505 | 601 | 602 | 603 | 603e | ec603e \
  | 604 | 604e | 620 | 630 | 740 | 750 | 7400 | 7450 \
- | a2 | e300c[23] | 854[08] | e500mc \
+ | a2 | e300c[23] | 854[08] | e500mc | e500mc64 \
  | 801 | 821 | 823 | 860 | 970 | G3 | G4 | G5 | cell)
  # OK
  ;;
diff -ruN gcc-4.5-20091027/gcc/doc/invoke.texi gcc-4.5-e500mc64-20091027/gcc/doc/invoke.texi
--- gcc-4.5-20091027/gcc/doc/invoke.texi 2009-10-27 10:42:17.000000000 -0500
+++ gcc-4.5-e500mc64-20091027/gcc/doc/invoke.texi 2009-11-03 12:52:17.000000000 -0600
@@ -14656,10 +14656,10 @@
 @samp{603e}, @samp{604}, @samp{604e}, @samp{620}, @samp{630}, @samp{740},
 @samp{7400}, @samp{7450}, @samp{750}, @samp{801}, @samp{821}, @samp{823},
 @samp{860}, @samp{970}, @samp{8540}, @samp{a2}, @samp{e300c2},
-@samp{e300c3}, @samp{e500mc}, @samp{ec603e}, @samp{G3}, @samp{G4}, @samp{G5},
-@samp{power}, @samp{power2}, @samp{power3}, @samp{power4},
-@samp{power5}, @samp{power5+}, @samp{power6}, @samp{power6x}, @samp{power7},
-@samp{common}, @samp{powerpc}, @samp{powerpc64}, @samp{rios},
+@samp{e300c3}, @samp{e500mc}, @samp{e500mc64}, @samp{ec603e}, @samp{G3},
+@samp{G4}, @samp{G5}, @samp{power}, @samp{power2}, @samp{power3},
+@samp{power4}, @samp{power5}, @samp{power5+}, @samp{power6}, @samp{power6x},
+@samp{power7}, @samp{common}, @samp{powerpc}, @samp{powerpc64}, @samp{rios},
 @samp{rios1}, @samp{rios2}, @samp{rsc}, and @samp{rs64}.
 
 @option{-mcpu=common} selects a completely generic processor.  Code
diff -ruN gcc-4.5-20091027/gcc/testsuite/gcc.target/powerpc/ppc-eq0-1.c gcc-4.5-e500mc64-20091027/gcc/testsuite/gcc.target/powerpc/ppc-eq0-1.c
--- gcc-4.5-20091027/gcc/testsuite/gcc.target/powerpc/ppc-eq0-1.c 2009-10-27 10:42:56.000000000 -0500
+++ gcc-4.5-e500mc64-20091027/gcc/testsuite/gcc.target/powerpc/ppc-eq0-1.c 2009-11-03 10:35:53.000000000 -0600
@@ -7,4 +7,4 @@
   return x == 0;
 }
 
-/* { dg-final { scan-assembler "cntlzw" } } */
+/* { dg-final { scan-assembler "cntlzw|isel" } } */

Re: {RFA] PowerPC e500mc64 core support

by David Edelsohn-3 :: Rate this Message:

Reply to Author | View Threaded | Show Only this Message

Edmar,

The support for the processor itself is okay: the scheduling, the cost
model, etc.

The change in rs6000_override_options to set rs6000_align_branches is
indented incorrectly.

The changes to the abs patterns seem superficially okay.

I need to review the rs6000_emit_sISEL function more carefully.

What is not okay are the changes to

 (define_expand "floatdidf2"
 (define_insn "*floatdidf2_fpr"
 (define_expand "fix_truncdfdi2"
 (define_insn "*fix_truncdfdi2_fpr"

Either e500mc64 is a 64 bit processor or not.  Either it sets
MASK_POWERPC64 or not.  Either it operates in the 32 bit subset or
not.  Either it follows the Linux ABI or not.  Either all processors
with E500_SINGLE or E500_DOUBLE feature work this way or not.  It
cannot operate in 32 bit mode "except for this instruction".  If
Freescale really wants to use that instruction in 32 bit mode for
those operations, use custom assembly in libgcc, then it always will
work in future iterations because it always can fall back to default
libgcc without the special instructions.

Creating ABIs that vary with the processor is a road to hell.  If
Freescale wants to do that, it can supply private patches to customers
or through partners because it is going to be incompatible with the
rest of the PowerPC world anyway and require a custom distribution and
toolchain.  Someone should have been thinking ahead more than one
processor generation.

David

Re: {RFA] PowerPC e500mc64 core support

by Edmar Wienskoski-RA8797-2 :: Rate this Message:

Reply to Author | View Threaded | Show Only this Message

David,

We've reviewed our goals and revised the patches with your
comments in mind. We think that this version should address
your concerns and welcome your feedback if this is not the case.

I am still using the same subversion revision 153598 from 2009-10-27

I re-run the regressions tests for both e500mc and 970 targets under
these conditions:
--enable-checking --disable-decimal-float --enable-languages=c,c++,fortran

Please let us know if you see any further concerns prior to applying.

Regards,
Edmar



2009-11-03  Edmar Wienskoski  edmar@...

        * config.gcc (cpu_is_64bit): Add new core e500mc64.
        (powerpc*-*-*): Add new core e500mc64.
        * config/rs6000/e500mc64.md: New file.
        * config/rs6000/rs6000.c (processor_costs): Add new costs for
        e500mc64.
        (rs6000_override_options): Add e500mc64 case to
        processor_target_table. Altivec and Spe options not allowed with
        e500mc64. Disable string instructions for e500mc64. Enable branch
        targets alignment for both e500mc and e500mc64. Initialize
        rs6000_cost for e500mc64.
        (rs6000_emit_sISEL): New function.
        (rs6000_emit_sCOND): Call rs6000_emit_sISEL for isel targets.
        (rs6000_emit_int_cmove): Fix mode of 64 bit isel pattern
        generation.
        (rs6000_issue_rate): Set issue rate for e500mc64.
        (rs6000_rtx_costs): Set more accurate cost for mfcr instruction
        on architectures with isel.
        * config/rs6000/rs6000-protos.h: Declare new function.
        * config/rs6000/rs6000.h (processor_type): Add
        PROCESSOR_PPCE500MC64.
        (ASM_CPU_SPEC): Add e500mc64.
        * config/rs6000/rs6000.md (define_attr "cpu"): Add ppce500mc64.
        Include e500mc64.md.
        (abssi2_isel): Expand pattern to handle DImode.
        (nabs<mode>2_isel): New pattern.
        (absdi2): Change pattern to handle 64 bit isel targets.
        (absdi2_internal): Exclude isel targets.
        (nabsdi2): Exclude isel targets.
        * doc/invoke.texi: Add e500mc64 to list of cpus.


2009-11-03  Edmar Wienskoski  edmar@...

        * gcc.target/powerpc/ppc-eq0-1.c: Adjust testcase for isel
        targets.


diff -ruN gcc-4.5-20091027/gcc/config/rs6000/e500mc64.md gcc-4.5-e500mc64-20091027/gcc/config/rs6000/e500mc64.md
--- gcc-4.5-20091027/gcc/config/rs6000/e500mc64.md 1969-12-31 18:00:00.000000000 -0600
+++ gcc-4.5-e500mc64-20091027/gcc/config/rs6000/e500mc64.md 2009-11-06 15:42:17.000000000 -0600
@@ -0,0 +1,191 @@
+;; Pipeline description for Motorola PowerPC e500mc64 core.
+;;   Copyright (C) 2009 Free Software Foundation, Inc.
+;;   Contributed by Edmar Wienskoski (edmar@...)
+;;
+;; 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/>.
+;;
+;; e500mc64 64-bit SU(2), LSU, FPU, BPU
+;; Max issue 3 insns/clock cycle (includes 1 branch)
+
+(define_automaton "e500mc64_most,e500mc64_long,e500mc64_retire")
+(define_cpu_unit "e500mc64_decode_0,e500mc64_decode_1" "e500mc64_most")
+(define_cpu_unit "e500mc64_issue_0,e500mc64_issue_1"   "e500mc64_most")
+(define_cpu_unit "e500mc64_retire_0,e500mc64_retire_1" "e500mc64_retire")
+
+;; SU.
+(define_cpu_unit "e500mc64_su0_stage0,e500mc64_su1_stage0" "e500mc64_most")
+
+;; MU.
+(define_cpu_unit "e500mc64_mu_stage0,e500mc64_mu_stage1" "e500mc64_most")
+(define_cpu_unit "e500mc64_mu_stage2,e500mc64_mu_stage3" "e500mc64_most")
+
+;; Non-pipelined division.
+(define_cpu_unit "e500mc64_mu_div" "e500mc64_long")
+
+;; LSU.
+(define_cpu_unit "e500mc64_lsu" "e500mc64_most")
+
+;; FPU.
+(define_cpu_unit "e500mc64_fpu" "e500mc64_most")
+
+;; Branch unit.
+(define_cpu_unit "e500mc64_bu" "e500mc64_most")
+
+;; The following units are used to make the automata deterministic.
+(define_cpu_unit "present_e500mc64_decode_0" "e500mc64_most")
+(define_cpu_unit "present_e500mc64_issue_0" "e500mc64_most")
+(define_cpu_unit "present_e500mc64_retire_0" "e500mc64_retire")
+(define_cpu_unit "present_e500mc64_su0_stage0" "e500mc64_most")
+
+;; The following sets to make automata deterministic when option ndfa is used.
+(presence_set "present_e500mc64_decode_0" "e500mc64_decode_0")
+(presence_set "present_e500mc64_issue_0" "e500mc64_issue_0")
+(presence_set "present_e500mc64_retire_0" "e500mc64_retire_0")
+(presence_set "present_e500mc64_su0_stage0" "e500mc64_su0_stage0")
+
+;; Some useful abbreviations.
+(define_reservation "e500mc64_decode"
+    "e500mc64_decode_0|e500mc64_decode_1+present_e500mc64_decode_0")
+(define_reservation "e500mc64_issue"
+    "e500mc64_issue_0|e500mc64_issue_1+present_e500mc64_issue_0")
+(define_reservation "e500mc64_retire"
+   "e500mc64_retire_0|e500mc64_retire_1+present_e500mc64_retire_0")
+(define_reservation "e500mc64_su_stage0"
+   "e500mc64_su0_stage0|e500mc64_su1_stage0+present_e500mc64_su0_stage0")
+
+;; Simple SU insns.
+(define_insn_reservation "e500mc64_su" 1
+  (and (eq_attr "type" "integer,insert_word,insert_dword,delayed_compare,\
+ shift,cntlz,exts")
+       (eq_attr "cpu" "ppce500mc64"))
+  "e500mc64_decode,e500mc64_issue+e500mc64_su_stage0+e500mc64_retire")
+
+(define_insn_reservation "e500mc64_su2" 2
+  (and (eq_attr "type" "cmp,compare,delayed_compare,fast_compare,trap")
+       (eq_attr "cpu" "ppce500mc64"))
+  "e500mc64_decode,e500mc64_issue+e500mc64_su_stage0,e500mc64_retire")
+
+(define_insn_reservation "e500mc64_delayed" 2
+  (and (eq_attr "type" "var_shift_rotate,var_delayed_compare")
+       (eq_attr "cpu" "ppce500mc64"))
+  "e500mc64_decode,e500mc64_issue+e500mc64_su_stage0,e500mc64_retire")
+
+(define_insn_reservation "e500mc64_two" 2
+  (and (eq_attr "type" "two")
+       (eq_attr "cpu" "ppce500mc64"))
+  "e500mc64_decode,e500mc64_issue+e500mc64_su_stage0+e500mc64_retire,\
+   e500mc64_issue+e500mc64_su_stage0+e500mc64_retire")
+
+(define_insn_reservation "e500mc64_three" 3
+  (and (eq_attr "type" "three")
+       (eq_attr "cpu" "ppce500mc64"))
+  "e500mc64_decode,e500mc64_issue+e500mc64_su_stage0+e500mc64_retire,\
+   e500mc64_issue+e500mc64_su_stage0+e500mc64_retire,\
+   e500mc64_issue+e500mc64_su_stage0+e500mc64_retire")
+
+;; Multiply.
+(define_insn_reservation "e500mc64_multiply" 4
+  (and (eq_attr "type" "imul,imul2,imul3,imul_compare")
+       (eq_attr "cpu" "ppce500mc64"))
+  "e500mc64_decode,e500mc64_issue+e500mc64_mu_stage0,e500mc64_mu_stage1,\
+   e500mc64_mu_stage2,e500mc64_mu_stage3+e500mc64_retire")
+
+;; Divide. We use the average latency time here.
+(define_insn_reservation "e500mc64_divide" 14
+  (and (eq_attr "type" "idiv")
+       (eq_attr "cpu" "ppce500mc64"))
+  "e500mc64_decode,e500mc64_issue+e500mc64_mu_stage0+e500mc64_mu_div,\
+   e500mc64_mu_div*13")
+
+;; Branch.
+(define_insn_reservation "e500mc64_branch" 1
+  (and (eq_attr "type" "jmpreg,branch,isync")
+       (eq_attr "cpu" "ppce500mc64"))
+  "e500mc64_decode,e500mc64_bu,e500mc64_retire")
+
+;; CR logical.
+(define_insn_reservation "e500mc64_cr_logical" 1
+  (and (eq_attr "type" "cr_logical,delayed_cr")
+       (eq_attr "cpu" "ppce500mc64"))
+  "e500mc64_decode,e500mc64_bu,e500mc64_retire")
+
+;; Mfcr.
+(define_insn_reservation "e500mc64_mfcr" 4
+  (and (eq_attr "type" "mfcr")
+       (eq_attr "cpu" "ppce500mc64"))
+  "e500mc64_decode,e500mc64_issue+e500mc64_su1_stage0,e500mc64_su1_stage0*3+e500mc64_retire")
+
+;; Mtcrf.
+(define_insn_reservation "e500mc64_mtcrf" 1
+  (and (eq_attr "type" "mtcr")
+       (eq_attr "cpu" "ppce500mc64"))
+  "e500mc64_decode,e500mc64_issue+e500mc64_su1_stage0+e500mc64_retire")
+
+;; Mtjmpr.
+(define_insn_reservation "e500mc64_mtjmpr" 1
+  (and (eq_attr "type" "mtjmpr,mfjmpr")
+       (eq_attr "cpu" "ppce500mc64"))
+  "e500mc64_decode,e500mc64_issue+e500mc64_su_stage0+e500mc64_retire")
+
+;; Brinc.
+(define_insn_reservation "e500mc64_brinc" 1
+  (and (eq_attr "type" "brinc")
+       (eq_attr "cpu" "ppce500mc64"))
+  "e500mc64_decode,e500mc64_issue+e500mc64_su_stage0+e500mc64_retire")
+
+;; Loads.
+(define_insn_reservation "e500mc64_load" 3
+  (and (eq_attr "type" "load,load_ext,load_ext_u,load_ext_ux,load_ux,load_u,\
+ load_l,sync")
+       (eq_attr "cpu" "ppce500mc64"))
+  "e500mc64_decode,e500mc64_issue+e500mc64_lsu,nothing,e500mc64_retire")
+
+(define_insn_reservation "e500mc64_fpload" 4
+  (and (eq_attr "type" "fpload,fpload_ux,fpload_u")
+       (eq_attr "cpu" "ppce500mc64"))
+  "e500mc64_decode,e500mc64_issue+e500mc64_lsu,nothing*2,e500mc64_retire")
+
+;; Stores.
+(define_insn_reservation "e500mc64_store" 3
+  (and (eq_attr "type" "store,store_ux,store_u,store_c")
+       (eq_attr "cpu" "ppce500mc64"))
+  "e500mc64_decode,e500mc64_issue+e500mc64_lsu,nothing,e500mc64_retire")
+
+(define_insn_reservation "e500mc64_fpstore" 3
+  (and (eq_attr "type" "fpstore,fpstore_ux,fpstore_u")
+       (eq_attr "cpu" "ppce500mc64"))
+  "e500mc64_decode,e500mc64_issue+e500mc64_lsu,nothing,e500mc64_retire")
+
+;; The following ignores the retire unit to avoid a large automata.
+
+;; FP.
+(define_insn_reservation "e500mc64_float" 7
+  (and (eq_attr "type" "fpsimple,fp,fpcompare,dmul")
+       (eq_attr "cpu" "ppce500mc64"))
+  "e500mc64_decode,e500mc64_issue+e500mc64_fpu")
+; "e500mc64_decode,e500mc64_issue+e500mc64_fpu,nothing*5,e500mc64_retire")
+
+;; FP divides are not pipelined.
+(define_insn_reservation "e500mc64_sdiv" 20
+  (and (eq_attr "type" "sdiv")
+       (eq_attr "cpu" "ppce500mc64"))
+  "e500mc64_decode,e500mc64_issue+e500mc64_fpu,e500mc64_fpu*19")
+
+(define_insn_reservation "e500mc64_ddiv" 35
+  (and (eq_attr "type" "ddiv")
+       (eq_attr "cpu" "ppce500mc64"))
+  "e500mc64_decode,e500mc64_issue+e500mc64_fpu,e500mc64_fpu*34")
diff -ruN gcc-4.5-20091027/gcc/config/rs6000/rs6000.c gcc-4.5-e500mc64-20091027/gcc/config/rs6000/rs6000.c
--- gcc-4.5-20091027/gcc/config/rs6000/rs6000.c 2009-10-27 10:49:12.000000000 -0500
+++ gcc-4.5-e500mc64-20091027/gcc/config/rs6000/rs6000.c 2009-11-09 12:38:35.000000000 -0600
@@ -761,6 +761,25 @@
   1, /* prefetch streams /*/
 };
 
+/* Instruction costs on PPCE500MC64 processors.  */
+static const
+struct processor_costs ppce500mc64_cost = {
+  COSTS_N_INSNS (4),    /* mulsi */
+  COSTS_N_INSNS (4),    /* mulsi_const */
+  COSTS_N_INSNS (4),    /* mulsi_const9 */
+  COSTS_N_INSNS (4),    /* muldi */
+  COSTS_N_INSNS (14),   /* divsi */
+  COSTS_N_INSNS (14),   /* divdi */
+  COSTS_N_INSNS (4),    /* fp */
+  COSTS_N_INSNS (10),   /* dmul */
+  COSTS_N_INSNS (36),   /* sdiv */
+  COSTS_N_INSNS (66),   /* ddiv */
+  64, /* cache line size */
+  32, /* l1 cache */
+  128, /* l2 cache */
+  1, /* prefetch streams /*/
+};
+
 /* Instruction costs on POWER4 and POWER5 processors.  */
 static const
 struct processor_costs power4_cost = {
@@ -2217,6 +2236,8 @@
  {"e300c3", PROCESSOR_PPCE300C3, POWERPC_BASE_MASK},
  {"e500mc", PROCESSOR_PPCE500MC, POWERPC_BASE_MASK | MASK_PPC_GFXOPT
   | MASK_ISEL},
+ {"e500mc64", PROCESSOR_PPCE500MC64, POWERPC_BASE_MASK | MASK_POWERPC64
+  | MASK_PPC_GFXOPT | MASK_ISEL},
  {"860", PROCESSOR_MPCCORE, POWERPC_BASE_MASK | MASK_SOFT_FLOAT},
  {"970", PROCESSOR_POWER4,
   POWERPC_7400_MASK | MASK_PPC_GPOPT | MASK_MFCRF | MASK_POWERPC64},
@@ -2345,7 +2366,7 @@
     }
 
   if (rs6000_cpu == PROCESSOR_PPCE300C2 || rs6000_cpu == PROCESSOR_PPCE300C3
-      || rs6000_cpu == PROCESSOR_PPCE500MC)
+      || rs6000_cpu == PROCESSOR_PPCE500MC || rs6000_cpu == PROCESSOR_PPCE500MC64)
     {
       if (TARGET_ALTIVEC)
  error ("AltiVec not supported in this target");
@@ -2537,7 +2558,8 @@
   SUB3TARGET_OVERRIDE_OPTIONS;
 #endif
 
-  if (TARGET_E500 || rs6000_cpu == PROCESSOR_PPCE500MC)
+  if (TARGET_E500 || rs6000_cpu == PROCESSOR_PPCE500MC
+      || rs6000_cpu == PROCESSOR_PPCE500MC64)
     {
       /* The e500 and e500mc do not have string instructions, and we set
  MASK_STRING above when optimizing for size.  */
@@ -2574,7 +2596,9 @@
   rs6000_align_branch_targets = (rs6000_cpu == PROCESSOR_POWER4
  || rs6000_cpu == PROCESSOR_POWER5
  || rs6000_cpu == PROCESSOR_POWER6
- || rs6000_cpu == PROCESSOR_POWER7);
+ || rs6000_cpu == PROCESSOR_POWER7
+ || rs6000_cpu == PROCESSOR_PPCE500MC
+ || rs6000_cpu == PROCESSOR_PPCE500MC64);
 
   /* Allow debug switches to override the above settings.  */
   if (TARGET_ALWAYS_HINT > 0)
@@ -2776,6 +2800,10 @@
  rs6000_cost = &ppce500mc_cost;
  break;
 
+      case PROCESSOR_PPCE500MC64:
+ rs6000_cost = &ppce500mc64_cost;
+ break;
+
       case PROCESSOR_POWER4:
       case PROCESSOR_POWER5:
  rs6000_cost = &power4_cost;
@@ -15433,6 +15461,53 @@
 /* Emit the RTL for an sCOND pattern.  */
 
 void
+rs6000_emit_sISEL (enum machine_mode mode, rtx operands[])
+{
+  rtx condition_rtx;
+  enum machine_mode op_mode;
+  enum rtx_code cond_code;
+  rtx result = operands[0];
+
+  condition_rtx = rs6000_generate_compare (operands[1], mode);
+  cond_code = GET_CODE (condition_rtx);
+
+  op_mode = GET_MODE (XEXP (operands[1], 0));
+  if (op_mode == VOIDmode)
+    op_mode = GET_MODE (XEXP (operands[1], 1));
+
+  if (TARGET_POWERPC64 && GET_MODE (result) == DImode)
+    {
+      PUT_MODE (condition_rtx, DImode);
+      if (cond_code == GEU || cond_code == GTU || cond_code == LEU
+         || cond_code == LTU)
+       emit_insn (gen_isel_unsigned_di (result, condition_rtx,
+ force_reg (DImode, const1_rtx),
+ force_reg (DImode, const0_rtx),
+ XEXP (condition_rtx, 0)));
+      else
+       emit_insn (gen_isel_signed_di (result, condition_rtx,
+      force_reg (DImode, const1_rtx),
+      force_reg (DImode, const0_rtx),
+      XEXP (condition_rtx, 0)));
+    }
+  else
+    {
+      PUT_MODE (condition_rtx, SImode);
+      if (cond_code == GEU || cond_code == GTU || cond_code == LEU
+ || cond_code == LTU)
+       emit_insn (gen_isel_unsigned_si (result, condition_rtx,
+ force_reg (SImode, const1_rtx),
+ force_reg (SImode, const0_rtx),
+ XEXP (condition_rtx, 0)));
+      else
+       emit_insn (gen_isel_signed_si (result, condition_rtx,
+      force_reg (SImode, const1_rtx),
+      force_reg (SImode, const0_rtx),
+      XEXP (condition_rtx, 0)));
+    }
+}
+
+void
 rs6000_emit_sCOND (enum machine_mode mode, rtx operands[])
 {
   rtx condition_rtx;
@@ -15440,6 +15515,12 @@
   enum rtx_code cond_code;
   rtx result = operands[0];
 
+  if (TARGET_ISEL && (mode == SImode || mode == DImode))
+    {
+      rs6000_emit_sISEL (mode, operands);
+      return;
+    }
+
   condition_rtx = rs6000_generate_compare (operands[1], mode);
   cond_code = GET_CODE (condition_rtx);
 
@@ -16089,7 +16170,7 @@
 rs6000_emit_int_cmove (rtx dest, rtx op, rtx true_cond, rtx false_cond)
 {
   rtx condition_rtx, cr;
-  enum machine_mode mode = GET_MODE (XEXP (op, 0));
+  enum machine_mode mode = GET_MODE (dest);
 
   if (mode != SImode && (!TARGET_POWERPC64 || mode != DImode))
     return 0;
@@ -16097,7 +16178,7 @@
   /* We still have to do the compare, because isel doesn't do a
      compare, it just looks at the CRx bits set by a previous compare
      instruction.  */
-  condition_rtx = rs6000_generate_compare (op, SImode);
+  condition_rtx = rs6000_generate_compare (op, mode);
   cr = XEXP (condition_rtx, 0);
 
   if (mode == SImode)
@@ -21952,6 +22033,7 @@
   case CPU_PPCE300C2:
   case CPU_PPCE300C3:
   case CPU_PPCE500MC:
+  case CPU_PPCE500MC64:
     return 2;
   case CPU_RIOS2:
   case CPU_PPC476:
@@ -24765,7 +24847,10 @@
  {
   if (XEXP (x, 1) == const0_rtx)
     {
-      *total = COSTS_N_INSNS (2);
+      if (TARGET_ISEL)
+ *total = COSTS_N_INSNS (8);
+      else
+ *total = COSTS_N_INSNS (2);
       return true;
     }
   else if (mode == Pmode)
@@ -24781,7 +24866,10 @@
     case UNORDERED:
       if (outer_code == SET && (XEXP (x, 1) == const0_rtx))
  {
-  *total = COSTS_N_INSNS (2);
+  if (TARGET_ISEL)
+    *total = COSTS_N_INSNS (8);
+  else
+    *total = COSTS_N_INSNS (2);
   return true;
  }
       /* CC COMPARE.  */
diff -ruN gcc-4.5-20091027/gcc/config/rs6000/rs6000.h gcc-4.5-e500mc64-20091027/gcc/config/rs6000/rs6000.h
--- gcc-4.5-20091027/gcc/config/rs6000/rs6000.h 2009-10-27 10:49:12.000000000 -0500
+++ gcc-4.5-e500mc64-20091027/gcc/config/rs6000/rs6000.h 2009-11-04 10:34:41.000000000 -0600
@@ -158,6 +158,7 @@
 %{mcpu=e300c2: -me300} \
 %{mcpu=e300c3: -me300} \
 %{mcpu=e500mc: -me500mc} \
+%{mcpu=e500mc64: -me500mc64} \
 %{maltivec: -maltivec} \
 -many"
 
@@ -341,6 +342,7 @@
    PROCESSOR_PPCE300C2,
    PROCESSOR_PPCE300C3,
    PROCESSOR_PPCE500MC,
+   PROCESSOR_PPCE500MC64,
    PROCESSOR_POWER4,
    PROCESSOR_POWER5,
    PROCESSOR_POWER6,
diff -ruN gcc-4.5-20091027/gcc/config/rs6000/rs6000.md gcc-4.5-e500mc64-20091027/gcc/config/rs6000/rs6000.md
--- gcc-4.5-20091027/gcc/config/rs6000/rs6000.md 2009-10-27 10:49:12.000000000 -0500
+++ gcc-4.5-e500mc64-20091027/gcc/config/rs6000/rs6000.md 2009-11-06 14:19:45.000000000 -0600
@@ -139,7 +139,7 @@
 ;; Processor type -- this attribute must exactly match the processor_type
 ;; enumeration in rs6000.h.
 
-(define_attr "cpu" "rios1,rios2,rs64a,mpccore,ppc403,ppc405,ppc440,ppc476,ppc601,ppc603,ppc604,ppc604e,ppc620,ppc630,ppc750,ppc7400,ppc7450,ppc8540,ppce300c2,ppce300c3,ppce500mc,power4,power5,power6,power7,cell,ppca2"
+(define_attr "cpu" "rios1,rios2,rs64a,mpccore,ppc403,ppc405,ppc440,ppc476,ppc601,ppc603,ppc604,ppc604e,ppc620,ppc630,ppc750,ppc7400,ppc7450,ppc8540,ppce300c2,ppce300c3,ppce500mc,ppce500mc64,power4,power5,power6,power7,cell,ppca2"
   (const (symbol_ref "rs6000_cpu_attr")))
 
 
@@ -166,6 +166,7 @@
 (include "8540.md")
 (include "e300c2c3.md")
 (include "e500mc.md")
+(include "e500mc64.md")
 (include "power4.md")
 (include "power5.md")
 (include "power6.md")
@@ -2077,23 +2078,42 @@
   "TARGET_POWER"
   "abs %0,%1")
 
-(define_insn_and_split "abssi2_isel"
-  [(set (match_operand:SI 0 "gpc_reg_operand" "=r")
-        (abs:SI (match_operand:SI 1 "gpc_reg_operand" "b")))
-   (clobber (match_scratch:SI 2 "=&b"))
+(define_insn_and_split "abs<mode>2_isel"
+  [(set (match_operand:GPR 0 "gpc_reg_operand" "=r")
+        (abs:GPR (match_operand:GPR 1 "gpc_reg_operand" "b")))
+   (clobber (match_scratch:GPR 2 "=&b"))
    (clobber (match_scratch:CC 3 "=y"))]
   "TARGET_ISEL"
   "#"
   "&& reload_completed"
-  [(set (match_dup 2) (neg:SI (match_dup 1)))
+  [(set (match_dup 2) (neg:GPR (match_dup 1)))
    (set (match_dup 3)
  (compare:CC (match_dup 1)
     (const_int 0)))
    (set (match_dup 0)
- (if_then_else:SI (ge (match_dup 3)
-     (const_int 0))
- (match_dup 1)
- (match_dup 2)))]
+ (if_then_else:GPR (ge (match_dup 3)
+      (const_int 0))
+  (match_dup 1)
+  (match_dup 2)))]
+  "")
+
+(define_insn_and_split "nabs<mode>2_isel"
+  [(set (match_operand:GPR 0 "gpc_reg_operand" "=r")
+        (neg:GPR (abs:GPR (match_operand:GPR 1 "gpc_reg_operand" "b"))))
+   (clobber (match_scratch:GPR 2 "=&b"))
+   (clobber (match_scratch:CC 3 "=y"))]
+  "TARGET_ISEL"
+  "#"
+  "&& reload_completed"
+  [(set (match_dup 2) (neg:GPR (match_dup 1)))
+   (set (match_dup 3)
+ (compare:CC (match_dup 1)
+    (const_int 0)))
+   (set (match_dup 0)
+ (if_then_else:GPR (ge (match_dup 3)
+      (const_int 0))
+  (match_dup 2)
+  (match_dup 1)))]
   "")
 
 (define_insn_and_split "abssi2_nopower"
@@ -6767,8 +6787,9 @@
 (define_insn "*fix_truncdfdi2_fpr"
   [(set (match_operand:DI 0 "gpc_reg_operand" "=!d#r")
  (fix:DI (match_operand:DF 1 "gpc_reg_operand" "d")))]
-  "(TARGET_POWERPC64 || TARGET_XILINX_FPU) && TARGET_HARD_FLOAT
-    && TARGET_DOUBLE_FLOAT && TARGET_FPRS && !VECTOR_UNIT_VSX_P (DFmode)"
+  "(TARGET_POWERPC64 || TARGET_XILINX_FPU)
+    && TARGET_HARD_FLOAT && TARGET_DOUBLE_FLOAT && TARGET_FPRS
+    && !VECTOR_UNIT_VSX_P (DFmode)"
   "fctidz %0,%1"
   [(set_attr "type" "fp")])
 
@@ -7197,11 +7218,24 @@
 
 ;; PowerPC64 DImode operations.
 
-(define_insn_and_split "absdi2"
+(define_expand "absdi2"
+  [(set (match_operand:DI 0 "gpc_reg_operand" "")
+ (abs:DI (match_operand:DI 1 "gpc_reg_operand" "")))]
+  "TARGET_POWERPC64"
+  "
+{
+  if (TARGET_ISEL)
+    emit_insn (gen_absdi2_isel (operands[0], operands[1]));
+  else
+    emit_insn (gen_absdi2_internal (operands[0], operands[1]));
+  DONE;
+}")
+
+(define_insn_and_split "absdi2_internal"
   [(set (match_operand:DI 0 "gpc_reg_operand" "=&r,r")
         (abs:DI (match_operand:DI 1 "gpc_reg_operand" "r,0")))
    (clobber (match_scratch:DI 2 "=&r,&r"))]
-  "TARGET_POWERPC64"
+  "TARGET_POWERPC64 && !TARGET_ISEL"
   "#"
   "&& reload_completed"
   [(set (match_dup 2) (ashiftrt:DI (match_dup 1) (const_int 63)))
@@ -7213,7 +7247,7 @@
   [(set (match_operand:DI 0 "gpc_reg_operand" "=&r,r")
         (neg:DI (abs:DI (match_operand:DI 1 "gpc_reg_operand" "r,0"))))
    (clobber (match_scratch:DI 2 "=&r,&r"))]
-  "TARGET_POWERPC64"
+  "TARGET_POWERPC64 && !TARGET_ISEL"
   "#"
   "&& reload_completed"
   [(set (match_dup 2) (ashiftrt:DI (match_dup 1) (const_int 63)))
diff -ruN gcc-4.5-20091027/gcc/config/rs6000/rs6000-protos.h gcc-4.5-e500mc64-20091027/gcc/config/rs6000/rs6000-protos.h
--- gcc-4.5-20091027/gcc/config/rs6000/rs6000-protos.h 2009-10-27 10:49:12.000000000 -0500
+++ gcc-4.5-e500mc64-20091027/gcc/config/rs6000/rs6000-protos.h 2009-10-27 11:00:02.000000000 -0500
@@ -90,6 +90,7 @@
 extern bool rs6000_output_addr_const_extra (FILE *, rtx);
 extern enum rtx_code rs6000_reverse_condition (enum machine_mode,
        enum rtx_code);
+extern void rs6000_emit_sISEL (enum machine_mode, rtx[]);
 extern void rs6000_emit_sCOND (enum machine_mode, rtx[]);
 extern void rs6000_emit_cbranch (enum machine_mode, rtx[]);
 extern char * output_cbranch (rtx, const char *, int, rtx);
diff -ruN gcc-4.5-20091027/gcc/config.gcc gcc-4.5-e500mc64-20091027/gcc/config.gcc
--- gcc-4.5-20091027/gcc/config.gcc 2009-10-27 10:49:28.000000000 -0500
+++ gcc-4.5-e500mc64-20091027/gcc/config.gcc 2009-10-27 11:00:40.000000000 -0500
@@ -327,7 +327,7 @@
  extra_headers="ppc-asm.h altivec.h spe.h ppu_intrinsics.h paired.h spu2vmx.h vec_types.h si2vmx.h"
  need_64bit_hwint=yes
  case x$with_cpu in
-    xpowerpc64|xdefault64|x6[23]0|x970|xG5|xpower[34567]|xpower6x|xrs64a|xcell|xa2)
+    xpowerpc64|xdefault64|x6[23]0|x970|xG5|xpower[34567]|xpower6x|xrs64a|xcell|xa2|xe500mc64)
  cpu_is_64bit=yes
  ;;
  esac
@@ -3072,7 +3072,7 @@
  | 401 | 403 | 405 | 405fp | 440 | 440fp | 464 | 464fp \
  | 476 | 476fp | 505 | 601 | 602 | 603 | 603e | ec603e \
  | 604 | 604e | 620 | 630 | 740 | 750 | 7400 | 7450 \
- | a2 | e300c[23] | 854[08] | e500mc \
+ | a2 | e300c[23] | 854[08] | e500mc | e500mc64 \
  | 801 | 821 | 823 | 860 | 970 | G3 | G4 | G5 | cell)
  # OK
  ;;
diff -ruN gcc-4.5-20091027/gcc/doc/invoke.texi gcc-4.5-e500mc64-20091027/gcc/doc/invoke.texi
--- gcc-4.5-20091027/gcc/doc/invoke.texi 2009-10-27 10:42:17.000000000 -0500
+++ gcc-4.5-e500mc64-20091027/gcc/doc/invoke.texi 2009-11-03 12:52:17.000000000 -0600
@@ -14656,10 +14656,10 @@
 @samp{603e}, @samp{604}, @samp{604e}, @samp{620}, @samp{630}, @samp{740},
 @samp{7400}, @samp{7450}, @samp{750}, @samp{801}, @samp{821}, @samp{823},
 @samp{860}, @samp{970}, @samp{8540}, @samp{a2}, @samp{e300c2},
-@samp{e300c3}, @samp{e500mc}, @samp{ec603e}, @samp{G3}, @samp{G4}, @samp{G5},
-@samp{power}, @samp{power2}, @samp{power3}, @samp{power4},
-@samp{power5}, @samp{power5+}, @samp{power6}, @samp{power6x}, @samp{power7},
-@samp{common}, @samp{powerpc}, @samp{powerpc64}, @samp{rios},
+@samp{e300c3}, @samp{e500mc}, @samp{e500mc64}, @samp{ec603e}, @samp{G3},
+@samp{G4}, @samp{G5}, @samp{power}, @samp{power2}, @samp{power3},
+@samp{power4}, @samp{power5}, @samp{power5+}, @samp{power6}, @samp{power6x},
+@samp{power7}, @samp{common}, @samp{powerpc}, @samp{powerpc64}, @samp{rios},
 @samp{rios1}, @samp{rios2}, @samp{rsc}, and @samp{rs64}.
 
 @option{-mcpu=common} selects a completely generic processor.  Code
diff -ruN gcc-4.5-20091027/gcc/testsuite/gcc.target/powerpc/ppc-eq0-1.c gcc-4.5-e500mc64-20091027/gcc/testsuite/gcc.target/powerpc/ppc-eq0-1.c
--- gcc-4.5-20091027/gcc/testsuite/gcc.target/powerpc/ppc-eq0-1.c 2009-10-27 10:42:56.000000000 -0500
+++ gcc-4.5-e500mc64-20091027/gcc/testsuite/gcc.target/powerpc/ppc-eq0-1.c 2009-11-03 10:35:53.000000000 -0600
@@ -7,4 +7,4 @@
   return x == 0;
 }
 
-/* { dg-final { scan-assembler "cntlzw" } } */
+/* { dg-final { scan-assembler "cntlzw|isel" } } */


Re: {RFA] PowerPC e500mc64 core support

by David Edelsohn-3 :: Rate this Message:

Reply to Author | View Threaded | Show Only this Message

On Wed, Nov 11, 2009 at 12:42 PM, Edmar Wienskoski-RA8797
<edmar@...> wrote:

Hi, Edmar

This is a lot better.

>        (rs6000_rtx_costs): Set more accurate cost for mfcr instruction
>        on architectures with isel.

Does this ChangeLog entry mean materializing a truthvalue in a GPR?

@@ -24765,7 +24847,10 @@
       {
         if (XEXP (x, 1) == const0_rtx)
           {
-             *total = COSTS_N_INSNS (2);
+             if (TARGET_ISEL)
+               *total = COSTS_N_INSNS (8);
+             else
+               *total = COSTS_N_INSNS (2);
             return true;
           }
         else if (mode == Pmode)
@@ -24781,7 +24866,10 @@
    case UNORDERED:
      if (outer_code == SET && (XEXP (x, 1) == const0_rtx))
       {
-         *total = COSTS_N_INSNS (2);
+         if (TARGET_ISEL)
+           *total = COSTS_N_INSNS (8);
+         else
+           *total = COSTS_N_INSNS (2);
         return true;
       }
      /* CC COMPARE.  */

Why are you setting the value to "8"?  Current processors that
implement isel specify the latency as 1.  And e500mc64.md does not
define any scheduling information for isel!

Thanks, David