From 20d6e0e0f76d7458478ce75e2502add12de236d5 Mon Sep 17 00:00:00 2001 From: dje Date: Mon, 7 Dec 2009 15:34:21 +0000 Subject: [PATCH] 2009-12-07 Edmar Wienskoski * 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 (rs6000_emit_sISEL): Declare. * 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. (nabs2_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. git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@155044 138bc75d-0d04-0410-961f-82ee72b054a4 --- gcc/ChangeLog | 32 +++++++ gcc/config.gcc | 4 +- gcc/config/rs6000/e500mc64.md | 191 ++++++++++++++++++++++++++++++++++++++ gcc/config/rs6000/rs6000-protos.h | 1 + gcc/config/rs6000/rs6000.c | 102 ++++++++++++++++++-- gcc/config/rs6000/rs6000.h | 2 + gcc/config/rs6000/rs6000.md | 64 ++++++++++--- gcc/doc/invoke.texi | 8 +- 8 files changed, 376 insertions(+), 28 deletions(-) create mode 100644 gcc/config/rs6000/e500mc64.md diff --git a/gcc/ChangeLog b/gcc/ChangeLog index abc64a7..73c505b 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,35 @@ +2009-12-07 Edmar Wienskoski + + * 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 (rs6000_emit_sISEL): Declare. + * 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. + (nabs2_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-12-07 Uros Bizjak * config/i386/i386.md (any_or): New code iterator. diff --git a/gcc/config.gcc b/gcc/config.gcc index f7b23aa..ca9441f 100644 --- a/gcc/config.gcc +++ b/gcc/config.gcc @@ -327,7 +327,7 @@ powerpc*-*-*) 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 @@ -3081,7 +3081,7 @@ case "${target}" in | 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 --git a/gcc/config/rs6000/e500mc64.md b/gcc/config/rs6000/e500mc64.md new file mode 100644 index 0000000..8507514 --- /dev/null +++ b/gcc/config/rs6000/e500mc64.md @@ -0,0 +1,191 @@ +;; Pipeline description for Freescale PowerPC e500mc64 core. +;; Copyright (C) 2009 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 +;; . +;; +;; 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 --git a/gcc/config/rs6000/rs6000-protos.h b/gcc/config/rs6000/rs6000-protos.h index ca5e584..14b5496 100644 --- a/gcc/config/rs6000/rs6000-protos.h +++ b/gcc/config/rs6000/rs6000-protos.h @@ -90,6 +90,7 @@ extern void print_operand_address (FILE *, rtx); 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 --git a/gcc/config/rs6000/rs6000.c b/gcc/config/rs6000/rs6000.c index 9b03a9b..884b6e3 100644 --- a/gcc/config/rs6000/rs6000.c +++ b/gcc/config/rs6000/rs6000.c @@ -759,6 +759,25 @@ struct processor_costs ppce500mc_cost = { 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 = { @@ -2215,6 +2234,8 @@ rs6000_override_options (const char *default_cpu) {"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}, @@ -2343,7 +2364,7 @@ rs6000_override_options (const char *default_cpu) } 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"); @@ -2535,7 +2556,8 @@ rs6000_override_options (const char *default_cpu) 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. */ @@ -2572,7 +2594,9 @@ rs6000_override_options (const char *default_cpu) 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) @@ -2774,6 +2798,10 @@ rs6000_override_options (const char *default_cpu) rs6000_cost = &ppce500mc_cost; break; + case PROCESSOR_PPCE500MC64: + rs6000_cost = &ppce500mc64_cost; + break; + case PROCESSOR_POWER4: case PROCESSOR_POWER5: rs6000_cost = &power4_cost; @@ -15375,6 +15403,53 @@ rs6000_generate_compare (rtx cmp, enum machine_mode mode) /* 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; @@ -15382,6 +15457,12 @@ rs6000_emit_sCOND (enum machine_mode mode, rtx operands[]) 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); @@ -16031,7 +16112,7 @@ static int 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; @@ -16039,7 +16120,7 @@ rs6000_emit_int_cmove (rtx dest, rtx op, rtx true_cond, rtx false_cond) /* 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) @@ -21885,6 +21966,7 @@ rs6000_issue_rate (void) case CPU_PPCE300C2: case CPU_PPCE300C3: case CPU_PPCE500MC: + case CPU_PPCE500MC64: return 2; case CPU_RIOS2: case CPU_PPC476: @@ -24698,7 +24780,10 @@ rs6000_rtx_costs (rtx x, int code, int outer_code, int *total, { if (XEXP (x, 1) == const0_rtx) { - *total = COSTS_N_INSNS (2); + if (TARGET_ISEL && !TARGET_MFCRF) + *total = COSTS_N_INSNS (8); + else + *total = COSTS_N_INSNS (2); return true; } else if (mode == Pmode) @@ -24714,7 +24799,10 @@ rs6000_rtx_costs (rtx x, int code, int outer_code, int *total, case UNORDERED: if (outer_code == SET && (XEXP (x, 1) == const0_rtx)) { - *total = COSTS_N_INSNS (2); + if (TARGET_ISEL && !TARGET_MFCRF) + *total = COSTS_N_INSNS (8); + else + *total = COSTS_N_INSNS (2); return true; } /* CC COMPARE. */ diff --git a/gcc/config/rs6000/rs6000.h b/gcc/config/rs6000/rs6000.h index 4b1ca3d..a0c2ad7 100644 --- a/gcc/config/rs6000/rs6000.h +++ b/gcc/config/rs6000/rs6000.h @@ -158,6 +158,7 @@ %{mcpu=e300c2: -me300} \ %{mcpu=e300c3: -me300} \ %{mcpu=e500mc: -me500mc} \ +%{mcpu=e500mc64: -me500mc64} \ %{maltivec: -maltivec} \ -many" @@ -341,6 +342,7 @@ enum processor_type PROCESSOR_PPCE300C2, PROCESSOR_PPCE300C3, PROCESSOR_PPCE500MC, + PROCESSOR_PPCE500MC64, PROCESSOR_POWER4, PROCESSOR_POWER5, PROCESSOR_POWER6, diff --git a/gcc/config/rs6000/rs6000.md b/gcc/config/rs6000/rs6000.md index 0a7b0a5..5b69f70 100644 --- a/gcc/config/rs6000/rs6000.md +++ b/gcc/config/rs6000/rs6000.md @@ -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 "abs2_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 "nabs2_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 --git a/gcc/doc/invoke.texi b/gcc/doc/invoke.texi index 22fad8f..3a48494 100644 --- a/gcc/doc/invoke.texi +++ b/gcc/doc/invoke.texi @@ -14744,10 +14744,10 @@ Supported values for @var{cpu_type} are @samp{401}, @samp{403}, @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 -- 2.7.4