+2014-04-04 Bill Schmidt <wschmidt@linux.vnet.ibm.com>
+
+ Power8 HTM Support
+ Backport from mainline
+ 2013-12-03 Peter Bergner <bergner@vnet.ibm.com>
+
+ * config/rs6000/htmintrin.h (_TEXASR_INSTRUCTION_FETCH_CONFLICT): Fix
+ typo in macro name.
+ (_TEXASRU_INSTRUCTION_FETCH_CONFLICT): Likewise.
+
+ Backport from mainline r205233.
+ 2013-11-21 Peter Bergner <bergner@vnet.ibm.com>
+
+ * doc/extend.texi: Document htm builtins.
+
+ Backport from mainline
+ 2013-07-17 Iain Sandoe <iain@codesourcery.com>
+
+ * config/rs6000/darwin.h (REGISTER_NAMES): Add HTM registers.
+
+ Backport from mainline
+ 2013-07-16 Peter Bergner <bergner@vnet.ibm.com>
+
+ * config/rs6000/rs6000.c (rs6000_option_override_internal): Do not
+ enable extra ISA flags with TARGET_HTM.
+
+ 2013-07-16 Jakub Jelinek <jakub@redhat.com>
+ Peter Bergner <bergner@vnet.ibm.com>
+
+ * config/rs6000/rs6000.h (FIRST_PSEUDO_REGISTERS): Mention HTM
+ registers in the comment.
+ (DWARF_FRAME_REGISTERS): Subtract also the 3 HTM registers.
+ (DWARF_REG_TO_UNWIND_COLUMN): Use DWARF_FRAME_REGISTERS
+ rather than FIRST_PSEUDO_REGISTERS.
+
+ * config.gcc (powerpc*-*-*): Install htmintrin.h and htmxlintrin.h.
+ * config/rs6000/t-rs6000 (MD_INCLUDES): Add htm.md.
+ * config/rs6000/rs6000.opt: Add -mhtm option.
+ * config/rs6000/rs6000-cpus.def (POWERPC_MASKS): Add OPTION_MASK_HTM.
+ (ISA_2_7_MASKS_SERVER): Add OPTION_MASK_HTM.
+ * config/rs6000/rs6000-c.c (rs6000_target_modify_macros): Define
+ __HTM__ if the HTM instructions are available.
+ * config/rs6000/predicates.md (u3bit_cint_operand, u10bit_cint_operand)
+ (htm_spr_reg_operand): New define_predicates.
+ * config/rs6000/rs6000.md (define_attr "type"): Add htm.
+ (TFHAR_REGNO, TFIAR_REGNO, TEXASR_REGNO): New define_constants.
+ Include htm.md.
+ * config/rs6000/rs6000-builtin.def (BU_HTM_0, BU_HTM_1, BU_HTM_2)
+ (BU_HTM_3, BU_HTM_SPR0, BU_HTM_SPR1): Add support macros for defining
+ HTM builtin functions.
+ * config/rs6000/rs6000.c (RS6000_BUILTIN_H): New macro.
+ (rs6000_reg_names, alt_reg_names): Add HTM SPR register names.
+ (rs6000_init_hard_regno_mode_ok): Add support for HTM instructions.
+ (rs6000_builtin_mask_calculate): Likewise.
+ (rs6000_option_override_internal): Likewise.
+ (bdesc_htm): Add new HTM builtin support.
+ (htm_spr_num): New function.
+ (htm_spr_regno): Likewise.
+ (rs6000_htm_spr_icode): Likewise.
+ (htm_expand_builtin): Likewise.
+ (htm_init_builtins): Likewise.
+ (rs6000_expand_builtin): Add support for HTM builtin functions.
+ (rs6000_init_builtins): Likewise.
+ (rs6000_invalid_builtin, rs6000_opt_mask): Add support for -mhtm option.
+ * config/rs6000/rs6000.h (ASM_CPU_SPEC): Add support for -mhtm.
+ (TARGET_HTM, MASK_HTM): Define macros.
+ (FIRST_PSEUDO_REGISTER): Adjust for new HTM SPR registers.
+ (FIXED_REGISTERS): Likewise.
+ (CALL_USED_REGISTERS): Likewise.
+ (CALL_REALLY_USED_REGISTERS): Likewise.
+ (REG_ALLOC_ORDER): Likewise.
+ (enum reg_class): Likewise.
+ (REG_CLASS_NAMES): Likewise.
+ (REG_CLASS_CONTENTS): Likewise.
+ (REGISTER_NAMES): Likewise.
+ (ADDITIONAL_REGISTER_NAMES): Likewise.
+ (RS6000_BTC_SPR, RS6000_BTC_VOID, RS6000_BTC_32BIT, RS6000_BTC_64BIT)
+ (RS6000_BTC_MISC_MASK, RS6000_BTM_HTM): New macros.
+ (RS6000_BTM_COMMON): Add RS6000_BTM_HTM.
+ * config/rs6000/htm.md: New file.
+ * config/rs6000/htmintrin.h: New file.
+ * config/rs6000/htmxlintrin.h: New file.
+
2014-04-04 Bill Schmidt <wschmidt@linux.vnet.ibm.com>
Power8 Base Support
;;
powerpc*-*-*)
cpu_type=rs6000
- extra_headers="ppc-asm.h altivec.h spe.h ppu_intrinsics.h paired.h spu2vmx.h vec_types.h si2vmx.h"
+ extra_headers="ppc-asm.h altivec.h spe.h ppu_intrinsics.h paired.h spu2vmx.h vec_types.h si2vmx.h htmintrin.h htmxlintrin.h"
need_64bit_hwint=yes
case x$with_cpu in
xpowerpc64|xdefault64|x6[23]0|x970|xG5|xpower[345678]|xpower6x|xrs64a|xcell|xa2|xe500mc64|xe5500|Xe6500)
"v24", "v25", "v26", "v27", "v28", "v29", "v30", "v31", \
"vrsave", "vscr", \
"spe_acc", "spefscr", \
- "sfp" \
+ "sfp", \
+ "tfhar", "tfiar", "texasr" \
}
/* This outputs NAME to FILE. */
--- /dev/null
+;; Hardware Transactional Memory (HTM) patterns.
+;; Copyright (C) 2013 Free Software Foundation, Inc.
+;; Contributed by Peter Bergner <bergner@vnet.ibm.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
+;; <http://www.gnu.org/licenses/>.
+
+(define_constants
+ [(TFHAR_SPR 128)
+ (TFIAR_SPR 129)
+ (TEXASR_SPR 130)
+ (TEXASRU_SPR 131)
+ (MAX_HTM_OPERANDS 4)
+ ])
+
+;;
+;; UNSPEC_VOLATILE usage
+;;
+
+(define_c_enum "unspecv"
+ [UNSPECV_HTM_TABORT
+ UNSPECV_HTM_TABORTDC
+ UNSPECV_HTM_TABORTDCI
+ UNSPECV_HTM_TABORTWC
+ UNSPECV_HTM_TABORTWCI
+ UNSPECV_HTM_TBEGIN
+ UNSPECV_HTM_TCHECK
+ UNSPECV_HTM_TEND
+ UNSPECV_HTM_TRECHKPT
+ UNSPECV_HTM_TRECLAIM
+ UNSPECV_HTM_TSR
+ UNSPECV_HTM_MFSPR
+ UNSPECV_HTM_MTSPR
+ ])
+
+
+(define_expand "tabort"
+ [(set (match_dup 2)
+ (unspec_volatile:CC [(match_operand:SI 1 "int_reg_operand" "")]
+ UNSPECV_HTM_TABORT))
+ (set (match_dup 3)
+ (eq:SI (match_dup 2)
+ (const_int 0)))
+ (set (match_operand:SI 0 "int_reg_operand" "")
+ (minus:SI (const_int 1) (match_dup 3)))]
+ "TARGET_HTM"
+{
+ operands[2] = gen_rtx_REG (CCmode, CR0_REGNO);
+ operands[3] = gen_reg_rtx (SImode);
+})
+
+(define_insn "*tabort_internal"
+ [(set (match_operand:CC 1 "cc_reg_operand" "=x")
+ (unspec_volatile:CC [(match_operand:SI 0 "int_reg_operand" "r")]
+ UNSPECV_HTM_TABORT))]
+ "TARGET_HTM"
+ "tabort. %0"
+ [(set_attr "type" "htm")
+ (set_attr "length" "4")])
+
+(define_expand "tabortdc"
+ [(set (match_dup 4)
+ (unspec_volatile:CC [(match_operand 1 "u5bit_cint_operand" "n")
+ (match_operand:SI 2 "gpc_reg_operand" "r")
+ (match_operand:SI 3 "gpc_reg_operand" "r")]
+ UNSPECV_HTM_TABORTDC))
+ (set (match_dup 5)
+ (eq:SI (match_dup 4)
+ (const_int 0)))
+ (set (match_operand:SI 0 "int_reg_operand" "")
+ (minus:SI (const_int 1) (match_dup 5)))]
+ "TARGET_HTM"
+{
+ operands[4] = gen_rtx_REG (CCmode, CR0_REGNO);
+ operands[5] = gen_reg_rtx (SImode);
+})
+
+(define_insn "*tabortdc_internal"
+ [(set (match_operand:CC 3 "cc_reg_operand" "=x")
+ (unspec_volatile:CC [(match_operand 0 "u5bit_cint_operand" "n")
+ (match_operand:SI 1 "gpc_reg_operand" "r")
+ (match_operand:SI 2 "gpc_reg_operand" "r")]
+ UNSPECV_HTM_TABORTDC))]
+ "TARGET_HTM"
+ "tabortdc. %0,%1,%2"
+ [(set_attr "type" "htm")
+ (set_attr "length" "4")])
+
+(define_expand "tabortdci"
+ [(set (match_dup 4)
+ (unspec_volatile:CC [(match_operand 1 "u5bit_cint_operand" "n")
+ (match_operand:SI 2 "gpc_reg_operand" "r")
+ (match_operand 3 "s5bit_cint_operand" "n")]
+ UNSPECV_HTM_TABORTDCI))
+ (set (match_dup 5)
+ (eq:SI (match_dup 4)
+ (const_int 0)))
+ (set (match_operand:SI 0 "int_reg_operand" "")
+ (minus:SI (const_int 1) (match_dup 5)))]
+ "TARGET_HTM"
+{
+ operands[4] = gen_rtx_REG (CCmode, CR0_REGNO);
+ operands[5] = gen_reg_rtx (SImode);
+})
+
+(define_insn "*tabortdci_internal"
+ [(set (match_operand:CC 3 "cc_reg_operand" "=x")
+ (unspec_volatile:CC [(match_operand 0 "u5bit_cint_operand" "n")
+ (match_operand:SI 1 "gpc_reg_operand" "r")
+ (match_operand 2 "s5bit_cint_operand" "n")]
+ UNSPECV_HTM_TABORTDCI))]
+ "TARGET_HTM"
+ "tabortdci. %0,%1,%2"
+ [(set_attr "type" "htm")
+ (set_attr "length" "4")])
+
+(define_expand "tabortwc"
+ [(set (match_dup 4)
+ (unspec_volatile:CC [(match_operand 1 "u5bit_cint_operand" "n")
+ (match_operand:SI 2 "gpc_reg_operand" "r")
+ (match_operand:SI 3 "gpc_reg_operand" "r")]
+ UNSPECV_HTM_TABORTWC))
+ (set (match_dup 5)
+ (eq:SI (match_dup 4)
+ (const_int 0)))
+ (set (match_operand:SI 0 "int_reg_operand" "")
+ (minus:SI (const_int 1) (match_dup 5)))]
+ "TARGET_HTM"
+{
+ operands[4] = gen_rtx_REG (CCmode, CR0_REGNO);
+ operands[5] = gen_reg_rtx (SImode);
+})
+
+(define_insn "*tabortwc_internal"
+ [(set (match_operand:CC 3 "cc_reg_operand" "=x")
+ (unspec_volatile:CC [(match_operand 0 "u5bit_cint_operand" "n")
+ (match_operand:SI 1 "gpc_reg_operand" "r")
+ (match_operand:SI 2 "gpc_reg_operand" "r")]
+ UNSPECV_HTM_TABORTWC))]
+ "TARGET_HTM"
+ "tabortwc. %0,%1,%2"
+ [(set_attr "type" "htm")
+ (set_attr "length" "4")])
+
+(define_expand "tabortwci"
+ [(set (match_dup 4)
+ (unspec_volatile:CC [(match_operand 1 "u5bit_cint_operand" "n")
+ (match_operand:SI 2 "gpc_reg_operand" "r")
+ (match_operand 3 "s5bit_cint_operand" "n")]
+ UNSPECV_HTM_TABORTWCI))
+ (set (match_dup 5)
+ (eq:SI (match_dup 4)
+ (const_int 0)))
+ (set (match_operand:SI 0 "int_reg_operand" "")
+ (minus:SI (const_int 1) (match_dup 5)))]
+ "TARGET_HTM"
+{
+ operands[4] = gen_rtx_REG (CCmode, CR0_REGNO);
+ operands[5] = gen_reg_rtx (SImode);
+})
+
+(define_expand "ttest"
+ [(set (match_dup 1)
+ (unspec_volatile:CC [(const_int 0)
+ (reg:SI 0)
+ (const_int 0)]
+ UNSPECV_HTM_TABORTWCI))
+ (set (subreg:CC (match_dup 2) 0) (match_dup 1))
+ (set (match_dup 3) (lshiftrt:SI (match_dup 2) (const_int 24)))
+ (parallel [(set (match_operand:SI 0 "int_reg_operand" "")
+ (and:SI (match_dup 3) (const_int 15)))
+ (clobber (scratch:CC))])]
+ "TARGET_HTM"
+{
+ operands[1] = gen_rtx_REG (CCmode, CR0_REGNO);
+ operands[2] = gen_reg_rtx (SImode);
+ operands[3] = gen_reg_rtx (SImode);
+})
+
+(define_insn "*tabortwci_internal"
+ [(set (match_operand:CC 3 "cc_reg_operand" "=x")
+ (unspec_volatile:CC [(match_operand 0 "u5bit_cint_operand" "n")
+ (match_operand:SI 1 "gpc_reg_operand" "r")
+ (match_operand 2 "s5bit_cint_operand" "n")]
+ UNSPECV_HTM_TABORTWCI))]
+ "TARGET_HTM"
+ "tabortwci. %0,%1,%2"
+ [(set_attr "type" "htm")
+ (set_attr "length" "4")])
+
+(define_expand "tbegin"
+ [(set (match_dup 2)
+ (unspec_volatile:CC [(match_operand 1 "const_0_to_1_operand" "n")]
+ UNSPECV_HTM_TBEGIN))
+ (set (match_dup 3)
+ (eq:SI (match_dup 2)
+ (const_int 0)))
+ (set (match_operand:SI 0 "int_reg_operand" "")
+ (minus:SI (const_int 1) (match_dup 3)))]
+ "TARGET_HTM"
+{
+ operands[2] = gen_rtx_REG (CCmode, CR0_REGNO);
+ operands[3] = gen_reg_rtx (SImode);
+})
+
+(define_insn "*tbegin_internal"
+ [(set (match_operand:CC 1 "cc_reg_operand" "=x")
+ (unspec_volatile:CC [(match_operand 0 "const_0_to_1_operand" "n")]
+ UNSPECV_HTM_TBEGIN))]
+ "TARGET_HTM"
+ "tbegin. %0"
+ [(set_attr "type" "htm")
+ (set_attr "length" "4")])
+
+(define_expand "tcheck"
+ [(set (match_dup 2)
+ (unspec_volatile:CC [(match_operand 1 "u3bit_cint_operand" "n")]
+ UNSPECV_HTM_TCHECK))
+ (set (match_dup 3)
+ (eq:SI (match_dup 2)
+ (const_int 0)))
+ (set (match_operand:SI 0 "int_reg_operand" "")
+ (minus:SI (const_int 1) (match_dup 3)))]
+ "TARGET_HTM"
+{
+ operands[2] = gen_rtx_REG (CCmode, CR0_REGNO);
+ operands[3] = gen_reg_rtx (SImode);
+})
+
+(define_insn "*tcheck_internal"
+ [(set (match_operand:CC 1 "cc_reg_operand" "=x")
+ (unspec_volatile:CC [(match_operand 0 "u3bit_cint_operand" "n")]
+ UNSPECV_HTM_TCHECK))]
+ "TARGET_HTM"
+ "tcheck. %0"
+ [(set_attr "type" "htm")
+ (set_attr "length" "4")])
+
+(define_expand "tend"
+ [(set (match_dup 2)
+ (unspec_volatile:CC [(match_operand 1 "const_0_to_1_operand" "n")]
+ UNSPECV_HTM_TEND))
+ (set (match_dup 3)
+ (eq:SI (match_dup 2)
+ (const_int 0)))
+ (set (match_operand:SI 0 "int_reg_operand" "")
+ (minus:SI (const_int 1) (match_dup 3)))]
+ "TARGET_HTM"
+{
+ operands[2] = gen_rtx_REG (CCmode, CR0_REGNO);
+ operands[3] = gen_reg_rtx (SImode);
+})
+
+(define_insn "*tend_internal"
+ [(set (match_operand:CC 1 "cc_reg_operand" "=x")
+ (unspec_volatile:CC [(match_operand 0 "const_0_to_1_operand" "n")]
+ UNSPECV_HTM_TEND))]
+ "TARGET_HTM"
+ "tend. %0"
+ [(set_attr "type" "htm")
+ (set_attr "length" "4")])
+
+(define_expand "trechkpt"
+ [(set (match_dup 1)
+ (unspec_volatile:CC [(const_int 0)]
+ UNSPECV_HTM_TRECHKPT))
+ (set (match_dup 2)
+ (eq:SI (match_dup 1)
+ (const_int 0)))
+ (set (match_operand:SI 0 "int_reg_operand" "")
+ (minus:SI (const_int 1) (match_dup 2)))]
+ "TARGET_HTM"
+{
+ operands[1] = gen_rtx_REG (CCmode, CR0_REGNO);
+ operands[2] = gen_reg_rtx (SImode);
+})
+
+(define_insn "*trechkpt_internal"
+ [(set (match_operand:CC 0 "cc_reg_operand" "=x")
+ (unspec_volatile:CC [(const_int 0)]
+ UNSPECV_HTM_TRECHKPT))]
+ "TARGET_HTM"
+ "trechkpt."
+ [(set_attr "type" "htm")
+ (set_attr "length" "4")])
+
+(define_expand "treclaim"
+ [(set (match_dup 2)
+ (unspec_volatile:CC [(match_operand:SI 1 "gpc_reg_operand" "r")]
+ UNSPECV_HTM_TRECLAIM))
+ (set (match_dup 3)
+ (eq:SI (match_dup 2)
+ (const_int 0)))
+ (set (match_operand:SI 0 "int_reg_operand" "")
+ (minus:SI (const_int 1) (match_dup 3)))]
+ "TARGET_HTM"
+{
+ operands[2] = gen_rtx_REG (CCmode, CR0_REGNO);
+ operands[3] = gen_reg_rtx (SImode);
+})
+
+(define_insn "*treclaim_internal"
+ [(set (match_operand:CC 1 "cc_reg_operand" "=x")
+ (unspec_volatile:CC [(match_operand:SI 0 "gpc_reg_operand" "r")]
+ UNSPECV_HTM_TRECLAIM))]
+ "TARGET_HTM"
+ "treclaim. %0"
+ [(set_attr "type" "htm")
+ (set_attr "length" "4")])
+
+(define_expand "tsr"
+ [(set (match_dup 2)
+ (unspec_volatile:CC [(match_operand 1 "const_0_to_1_operand" "n")]
+ UNSPECV_HTM_TSR))
+ (set (match_dup 3)
+ (eq:SI (match_dup 2)
+ (const_int 0)))
+ (set (match_operand:SI 0 "int_reg_operand" "")
+ (minus:SI (const_int 1) (match_dup 3)))]
+ "TARGET_HTM"
+{
+ operands[2] = gen_rtx_REG (CCmode, CR0_REGNO);
+ operands[3] = gen_reg_rtx (SImode);
+})
+
+(define_insn "*tsr_internal"
+ [(set (match_operand:CC 1 "cc_reg_operand" "=x")
+ (unspec_volatile:CC [(match_operand 0 "const_0_to_1_operand" "n")]
+ UNSPECV_HTM_TSR))]
+ "TARGET_HTM"
+ "tsr. %0"
+ [(set_attr "type" "htm")
+ (set_attr "length" "4")])
+
+(define_insn "htm_mfspr_<mode>"
+ [(set (match_operand:P 0 "gpc_reg_operand" "=r")
+ (unspec_volatile:P [(match_operand 1 "u10bit_cint_operand" "n")
+ (match_operand:P 2 "htm_spr_reg_operand" "")]
+ UNSPECV_HTM_MFSPR))]
+ "TARGET_HTM"
+ "mfspr %0,%1";
+ [(set_attr "type" "htm")
+ (set_attr "length" "4")])
+
+(define_insn "htm_mtspr_<mode>"
+ [(set (match_operand:P 2 "htm_spr_reg_operand" "")
+ (unspec_volatile:P [(match_operand:P 0 "gpc_reg_operand" "r")
+ (match_operand 1 "u10bit_cint_operand" "n")]
+ UNSPECV_HTM_MTSPR))]
+ "TARGET_HTM"
+ "mtspr %1,%0";
+ [(set_attr "type" "htm")
+ (set_attr "length" "4")])
--- /dev/null
+/* Hardware Transactional Memory (HTM) intrinsics.
+ Copyright (C) 2013 Free Software Foundation, Inc.
+ Contributed by Peter Bergner <bergner@vnet.ibm.com>.
+
+ This file 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 of the License, or (at your option)
+ any later version.
+
+ This file 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.
+
+ Under Section 7 of GPL version 3, you are granted additional
+ permissions described in the GCC Runtime Library Exception, version
+ 3.1, as published by the Free Software Foundation.
+
+ You should have received a copy of the GNU General Public License and
+ a copy of the GCC Runtime Library Exception along with this program;
+ see the files COPYING3 and COPYING.RUNTIME respectively. If not, see
+ <http://www.gnu.org/licenses/>. */
+
+#ifndef __HTM__
+# error "HTM instruction set not enabled"
+#endif /* __HTM__ */
+
+#ifndef _HTMINTRIN_H
+#define _HTMINTRIN_H
+
+#include <stdint.h>
+
+typedef uint64_t texasr_t;
+typedef uint32_t texasru_t;
+typedef uint32_t texasrl_t;
+typedef uintptr_t tfiar_t;
+typedef uintptr_t tfhar_t;
+
+#define _HTM_STATE(CR0) ((CR0 >> 1) & 0x3)
+#define _HTM_NONTRANSACTIONAL 0x0
+#define _HTM_SUSPENDED 0x1
+#define _HTM_TRANSACTIONAL 0x2
+
+/* The following macros use the IBM bit numbering for BITNUM
+ as used in the ISA documentation. */
+
+#define _TEXASR_EXTRACT_BITS(TEXASR,BITNUM,SIZE) \
+ (((TEXASR) >> (63-(BITNUM))) & ((1<<(SIZE))-1))
+#define _TEXASRU_EXTRACT_BITS(TEXASR,BITNUM,SIZE) \
+ (((TEXASR) >> (31-(BITNUM))) & ((1<<(SIZE))-1))
+
+#define _TEXASR_FAILURE_CODE(TEXASR) \
+ _TEXASR_EXTRACT_BITS(TEXASR, 7, 8)
+#define _TEXASRU_FAILURE_CODE(TEXASRU) \
+ _TEXASRU_EXTRACT_BITS(TEXASRU, 7, 8)
+
+#define _TEXASR_FAILURE_PERSISTENT(TEXASR) \
+ _TEXASR_EXTRACT_BITS(TEXASR, 7, 1)
+#define _TEXASRU_FAILURE_PERSISTENT(TEXASRU) \
+ _TEXASRU_EXTRACT_BITS(TEXASRU, 7, 1)
+
+#define _TEXASR_DISALLOWED(TEXASR) \
+ _TEXASR_EXTRACT_BITS(TEXASR, 8, 1)
+#define _TEXASRU_DISALLOWED(TEXASRU) \
+ _TEXASRU_EXTRACT_BITS(TEXASRU, 8, 1)
+
+#define _TEXASR_NESTING_OVERFLOW(TEXASR) \
+ _TEXASR_EXTRACT_BITS(TEXASR, 9, 1)
+#define _TEXASRU_NESTING_OVERFLOW(TEXASRU) \
+ _TEXASRU_EXTRACT_BITS(TEXASRU, 9, 1)
+
+#define _TEXASR_FOOTPRINT_OVERFLOW(TEXASR) \
+ _TEXASR_EXTRACT_BITS(TEXASR, 10, 1)
+#define _TEXASRU_FOOTPRINT_OVERFLOW(TEXASRU) \
+ _TEXASRU_EXTRACT_BITS(TEXASRU, 10, 1)
+
+#define _TEXASR_SELF_INDUCED_CONFLICT(TEXASR) \
+ _TEXASR_EXTRACT_BITS(TEXASR, 11, 1)
+#define _TEXASRU_SELF_INDUCED_CONFLICT(TEXASRU) \
+ _TEXASRU_EXTRACT_BITS(TEXASRU, 11, 1)
+
+#define _TEXASR_NON_TRANSACTIONAL_CONFLICT(TEXASR) \
+ _TEXASR_EXTRACT_BITS(TEXASR, 12, 1)
+#define _TEXASRU_NON_TRANSACTIONAL_CONFLICT(TEXASRU) \
+ _TEXASRU_EXTRACT_BITS(TEXASRU, 12, 1)
+
+#define _TEXASR_TRANSACTION_CONFLICT(TEXASR) \
+ _TEXASR_EXTRACT_BITS(TEXASR, 13, 1)
+#define _TEXASRU_TRANSACTION_CONFLICT(TEXASRU) \
+ _TEXASRU_EXTRACT_BITS(TEXASRU, 13, 1)
+
+#define _TEXASR_TRANSLATION_INVALIDATION_CONFLICT(TEXASR) \
+ _TEXASR_EXTRACT_BITS(TEXASR, 14, 1)
+#define _TEXASRU_TRANSLATION_INVALIDATION_CONFLICT(TEXASRU) \
+ _TEXASRU_EXTRACT_BITS(TEXASRU, 14, 1)
+
+#define _TEXASR_IMPLEMENTAION_SPECIFIC(TEXASR) \
+ _TEXASR_EXTRACT_BITS(TEXASR, 15, 1)
+#define _TEXASRU_IMPLEMENTAION_SPECIFIC(TEXASRU) \
+ _TEXASRU_EXTRACT_BITS(TEXASRU, 15, 1)
+
+#define _TEXASR_INSTRUCTION_FETCH_CONFLICT(TEXASR) \
+ _TEXASR_EXTRACT_BITS(TEXASR, 16, 1)
+#define _TEXASRU_INSTRUCTION_FETCH_CONFLICT(TEXASRU) \
+ _TEXASRU_EXTRACT_BITS(TEXASRU, 16, 1)
+
+#define _TEXASR_ABORT(TEXASR) \
+ _TEXASR_EXTRACT_BITS(TEXASR, 31, 1)
+#define _TEXASRU_ABORT(TEXASRU) \
+ _TEXASRU_EXTRACT_BITS(TEXASRU, 31, 1)
+
+
+#define _TEXASR_SUSPENDED(TEXASR) \
+ _TEXASR_EXTRACT_BITS(TEXASR, 32, 1)
+
+#define _TEXASR_PRIVILEGE(TEXASR) \
+ _TEXASR_EXTRACT_BITS(TEXASR, 35, 2)
+
+#define _TEXASR_FAILURE_SUMMARY(TEXASR) \
+ _TEXASR_EXTRACT_BITS(TEXASR, 36, 1)
+
+#define _TEXASR_TFIAR_EXACT(TEXASR) \
+ _TEXASR_EXTRACT_BITS(TEXASR, 37, 1)
+
+#define _TEXASR_ROT(TEXASR) \
+ _TEXASR_EXTRACT_BITS(TEXASR, 38, 1)
+
+#define _TEXASR_TRANSACTION_LEVEL(TEXASR) \
+ _TEXASR_EXTRACT_BITS(TEXASR, 63, 12)
+
+#endif /* _HTMINTRIN_H */
--- /dev/null
+/* XL compiler Hardware Transactional Memory (HTM) execution intrinsics.
+ Copyright (C) 2013 Free Software Foundation, Inc.
+ Contributed by Peter Bergner <bergner@vnet.ibm.com>.
+
+ This file 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 of the License, or (at your option)
+ any later version.
+
+ This file 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.
+
+ Under Section 7 of GPL version 3, you are granted additional
+ permissions described in the GCC Runtime Library Exception, version
+ 3.1, as published by the Free Software Foundation.
+
+ You should have received a copy of the GNU General Public License and
+ a copy of the GCC Runtime Library Exception along with this program;
+ see the files COPYING3 and COPYING.RUNTIME respectively. If not, see
+ <http://www.gnu.org/licenses/>. */
+
+#ifndef __HTM__
+# error "HTM instruction set not enabled"
+#endif /* __HTM__ */
+
+#ifndef _HTMXLINTRIN_H
+#define _HTMXLINTRIN_H
+
+#include <stdint.h>
+#include <htmintrin.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#define _TEXASR_PTR(TM_BUF) \
+ ((texasr_t *)((TM_BUF)+0))
+#define _TEXASRU_PTR(TM_BUF) \
+ ((texasru_t *)((TM_BUF)+0))
+#define _TEXASRL_PTR(TM_BUF) \
+ ((texasrl_t *)((TM_BUF)+4))
+#define _TFIAR_PTR(TM_BUF) \
+ ((tfiar_t *)((TM_BUF)+8))
+
+typedef char TM_buff_type[16];
+
+extern __inline long
+__attribute__ ((__gnu_inline__, __always_inline__, __artificial__))
+__TM_simple_begin (void)
+{
+ if (__builtin_expect (__builtin_tbegin (0), 1))
+ return 1;
+ return 0;
+}
+
+extern __inline long
+__attribute__ ((__gnu_inline__, __always_inline__, __artificial__))
+__TM_begin (void* const TM_buff)
+{
+ *_TEXASRL_PTR (TM_buff) = 0;
+ if (__builtin_expect (__builtin_tbegin (0), 1))
+ return 1;
+#ifdef __powerpc64__
+ *_TEXASR_PTR (TM_buff) = __builtin_get_texasr ();
+#else
+ *_TEXASRU_PTR (TM_buff) = __builtin_get_texasru ();
+ *_TEXASRL_PTR (TM_buff) = __builtin_get_texasr ();
+#endif
+ *_TFIAR_PTR (TM_buff) = __builtin_get_tfiar ();
+ return 0;
+}
+
+extern __inline long
+__attribute__ ((__gnu_inline__, __always_inline__, __artificial__))
+__TM_end (void)
+{
+ if (__builtin_expect (__builtin_tend (0), 1))
+ return 1;
+ return 0;
+}
+
+extern __inline void
+__attribute__ ((__gnu_inline__, __always_inline__, __artificial__))
+__TM_abort (void)
+{
+ __builtin_tabort (0);
+}
+
+extern __inline void
+__attribute__ ((__gnu_inline__, __always_inline__, __artificial__))
+__TM_named_abort (unsigned char const code)
+{
+ __builtin_tabort (code);
+}
+
+extern __inline void
+__attribute__ ((__gnu_inline__, __always_inline__, __artificial__))
+__TM_resume (void)
+{
+ __builtin_tresume ();
+}
+
+extern __inline void
+__attribute__ ((__gnu_inline__, __always_inline__, __artificial__))
+__TM_suspend (void)
+{
+ __builtin_tsuspend ();
+}
+
+extern __inline long
+__attribute__ ((__gnu_inline__, __always_inline__, __artificial__))
+__TM_is_user_abort (void* const TM_buff)
+{
+ texasru_t texasru = *_TEXASRU_PTR (TM_buff);
+ return _TEXASRU_ABORT (texasru);
+}
+
+extern __inline long
+__attribute__ ((__gnu_inline__, __always_inline__, __artificial__))
+__TM_is_named_user_abort (void* const TM_buff, unsigned char *code)
+{
+ texasru_t texasru = *_TEXASRU_PTR (TM_buff);
+
+ *code = _TEXASRU_FAILURE_CODE (texasru);
+ return _TEXASRU_ABORT (texasru);
+}
+
+extern __inline long
+__attribute__ ((__gnu_inline__, __always_inline__, __artificial__))
+__TM_is_illegal (void* const TM_buff)
+{
+ texasru_t texasru = *_TEXASRU_PTR (TM_buff);
+ return _TEXASRU_DISALLOWED (texasru);
+}
+
+extern __inline long
+__attribute__ ((__gnu_inline__, __always_inline__, __artificial__))
+__TM_is_footprint_exceeded (void* const TM_buff)
+{
+ texasru_t texasru = *_TEXASRU_PTR (TM_buff);
+ return _TEXASRU_FOOTPRINT_OVERFLOW (texasru);
+}
+
+extern __inline long
+__attribute__ ((__gnu_inline__, __always_inline__, __artificial__))
+__TM_nesting_depth (void* const TM_buff)
+{
+ texasrl_t texasrl;
+
+ if (_HTM_STATE (__builtin_ttest ()) == _HTM_NONTRANSACTIONAL)
+ {
+ texasrl = *_TEXASRL_PTR (TM_buff);
+ if (!_TEXASR_FAILURE_SUMMARY (texasrl))
+ texasrl = 0;
+ }
+ else
+ texasrl = (texasrl_t) __builtin_get_texasr ();
+
+ return _TEXASR_TRANSACTION_LEVEL (texasrl);
+}
+
+extern __inline long
+__attribute__ ((__gnu_inline__, __always_inline__, __artificial__))
+__TM_is_nested_too_deep(void* const TM_buff)
+{
+ texasru_t texasru = *_TEXASRU_PTR (TM_buff);
+ return _TEXASRU_NESTING_OVERFLOW (texasru);
+}
+
+extern __inline long
+__attribute__ ((__gnu_inline__, __always_inline__, __artificial__))
+__TM_is_conflict(void* const TM_buff)
+{
+ texasru_t texasru = *_TEXASRU_PTR (TM_buff);
+ /* Return TEXASR bits 11 (Self-Induced Conflict) through
+ 14 (Translation Invalidation Conflict). */
+ return (_TEXASRU_EXTRACT_BITS (texasru, 14, 4)) ? 1 : 0;
+}
+
+extern __inline long
+__attribute__ ((__gnu_inline__, __always_inline__, __artificial__))
+__TM_is_failure_persistent(void* const TM_buff)
+{
+ texasru_t texasru = *_TEXASRU_PTR (TM_buff);
+ return _TEXASRU_FAILURE_PERSISTENT (texasru);
+}
+
+extern __inline long
+__attribute__ ((__gnu_inline__, __always_inline__, __artificial__))
+__TM_failure_address(void* const TM_buff)
+{
+ return *_TFIAR_PTR (TM_buff);
+}
+
+extern __inline long long
+__attribute__ ((__gnu_inline__, __always_inline__, __artificial__))
+__TM_failure_code(void* const TM_buff)
+{
+ return *_TEXASR_PTR (TM_buff);
+}
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* _HTMXLINTRIN_H */
(and (match_code "const_int")
(match_test "INTVAL (op) >= -16 && INTVAL (op) <= 15")))
+;; Return 1 if op is a unsigned 3-bit constant integer.
+(define_predicate "u3bit_cint_operand"
+ (and (match_code "const_int")
+ (match_test "INTVAL (op) >= 0 && INTVAL (op) <= 7")))
+
;; Return 1 if op is a unsigned 5-bit constant integer.
(define_predicate "u5bit_cint_operand"
(and (match_code "const_int")
(and (match_code "const_int")
(match_test "INTVAL (op) >= -128 && INTVAL (op) <= 127")))
+;; Return 1 if op is a unsigned 10-bit constant integer.
+(define_predicate "u10bit_cint_operand"
+ (and (match_code "const_int")
+ (match_test "INTVAL (op) >= 0 && INTVAL (op) <= 1023")))
+
;; Return 1 if op is a constant integer that can fit in a D field.
(define_predicate "short_cint_operand"
(and (match_code "const_int")
return (REGNO (op) != FIRST_GPR_REGNO);
})
+;; Return 1 if op is a HTM specific SPR register.
+(define_predicate "htm_spr_reg_operand"
+ (match_operand 0 "register_operand")
+{
+ if (!TARGET_HTM)
+ return 0;
+
+ if (GET_CODE (op) == SUBREG)
+ op = SUBREG_REG (op);
+
+ if (!REG_P (op))
+ return 0;
+
+ switch (REGNO (op))
+ {
+ case TFHAR_REGNO:
+ case TFIAR_REGNO:
+ case TEXASR_REGNO:
+ return 1;
+ default:
+ break;
+ }
+
+ /* Unknown SPR. */
+ return 0;
+})
+
;; Return 1 if op is a general purpose register that is an even register
;; which suitable for a load/store quad operation
(define_predicate "quad_int_reg_operand"
RS6000_BUILTIN_A -- ABS builtins
RS6000_BUILTIN_D -- DST builtins
RS6000_BUILTIN_E -- SPE EVSEL builtins.
+ RS6000_BUILTIN_H -- HTM builtins
RS6000_BUILTIN_P -- Altivec, VSX, ISA 2.07 vector predicate builtins
RS6000_BUILTIN_Q -- Paired floating point VSX predicate builtins
RS6000_BUILTIN_S -- SPE predicate builtins
#error "RS6000_BUILTIN_E is not defined."
#endif
+#ifndef RS6000_BUILTIN_H
+ #error "RS6000_BUILTIN_H is not defined."
+#endif
+
#ifndef RS6000_BUILTIN_P
#error "RS6000_BUILTIN_P is not defined."
#endif
| RS6000_BTC_TERNARY), \
CODE_FOR_nothing) /* ICODE */
+/* HTM convenience macros. */
+#define BU_HTM_0(ENUM, NAME, ATTR, ICODE) \
+ RS6000_BUILTIN_H (HTM_BUILTIN_ ## ENUM, /* ENUM */ \
+ "__builtin_" NAME, /* NAME */ \
+ RS6000_BTM_HTM, /* MASK */ \
+ RS6000_BTC_ ## ATTR, /* ATTR */ \
+ CODE_FOR_ ## ICODE) /* ICODE */
+
+#define BU_HTM_1(ENUM, NAME, ATTR, ICODE) \
+ RS6000_BUILTIN_H (HTM_BUILTIN_ ## ENUM, /* ENUM */ \
+ "__builtin_" NAME, /* NAME */ \
+ RS6000_BTM_HTM, /* MASK */ \
+ (RS6000_BTC_ ## ATTR /* ATTR */ \
+ | RS6000_BTC_UNARY), \
+ CODE_FOR_ ## ICODE) /* ICODE */
+
+#define BU_HTM_2(ENUM, NAME, ATTR, ICODE) \
+ RS6000_BUILTIN_H (HTM_BUILTIN_ ## ENUM, /* ENUM */ \
+ "__builtin_" NAME, /* NAME */ \
+ RS6000_BTM_HTM, /* MASK */ \
+ (RS6000_BTC_ ## ATTR /* ATTR */ \
+ | RS6000_BTC_BINARY), \
+ CODE_FOR_ ## ICODE) /* ICODE */
+
+#define BU_HTM_3(ENUM, NAME, ATTR, ICODE) \
+ RS6000_BUILTIN_H (HTM_BUILTIN_ ## ENUM, /* ENUM */ \
+ "__builtin_" NAME, /* NAME */ \
+ RS6000_BTM_HTM, /* MASK */ \
+ (RS6000_BTC_ ## ATTR /* ATTR */ \
+ | RS6000_BTC_TERNARY), \
+ CODE_FOR_ ## ICODE) /* ICODE */
+
+#define BU_HTM_SPR0(ENUM, NAME, ATTR, ICODE) \
+ RS6000_BUILTIN_H (HTM_BUILTIN_ ## ENUM, /* ENUM */ \
+ "__builtin_" NAME, /* NAME */ \
+ RS6000_BTM_HTM, /* MASK */ \
+ (RS6000_BTC_ ## ATTR /* ATTR */ \
+ | RS6000_BTC_SPR), \
+ CODE_FOR_ ## ICODE) /* ICODE */
+
+#define BU_HTM_SPR1(ENUM, NAME, ATTR, ICODE) \
+ RS6000_BUILTIN_H (HTM_BUILTIN_ ## ENUM, /* ENUM */ \
+ "__builtin_" NAME, /* NAME */ \
+ RS6000_BTM_HTM, /* MASK */ \
+ (RS6000_BTC_ ## ATTR /* ATTR */ \
+ | RS6000_BTC_UNARY \
+ | RS6000_BTC_SPR \
+ | RS6000_BTC_VOID), \
+ CODE_FOR_ ## ICODE) /* ICODE */
+
/* SPE convenience macros. */
#define BU_SPE_1(ENUM, NAME, ATTR, ICODE) \
RS6000_BUILTIN_1 (SPE_BUILTIN_ ## ENUM, /* ENUM */ \
BU_CRYPTO_OVERLOAD_3 (VPERMXOR, "vpermxor")
BU_CRYPTO_OVERLOAD_3 (VSHASIGMA, "vshasigma")
+\f
+/* HTM functions. */
+BU_HTM_1 (TABORT, "tabort", MISC, tabort)
+BU_HTM_3 (TABORTDC, "tabortdc", MISC, tabortdc)
+BU_HTM_3 (TABORTDCI, "tabortdci", MISC, tabortdci)
+BU_HTM_3 (TABORTWC, "tabortwc", MISC, tabortwc)
+BU_HTM_3 (TABORTWCI, "tabortwci", MISC, tabortwci)
+BU_HTM_1 (TBEGIN, "tbegin", MISC, tbegin)
+BU_HTM_1 (TCHECK, "tcheck", MISC, tcheck)
+BU_HTM_1 (TEND, "tend", MISC, tend)
+BU_HTM_0 (TENDALL, "tendall", MISC, tend)
+BU_HTM_0 (TRECHKPT, "trechkpt", MISC, trechkpt)
+BU_HTM_1 (TRECLAIM, "treclaim", MISC, treclaim)
+BU_HTM_0 (TRESUME, "tresume", MISC, tsr)
+BU_HTM_0 (TSUSPEND, "tsuspend", MISC, tsr)
+BU_HTM_1 (TSR, "tsr", MISC, tsr)
+BU_HTM_0 (TTEST, "ttest", MISC, ttest)
+
+BU_HTM_SPR0 (GET_TFHAR, "get_tfhar", MISC, nothing)
+BU_HTM_SPR1 (SET_TFHAR, "set_tfhar", MISC, nothing)
+BU_HTM_SPR0 (GET_TFIAR, "get_tfiar", MISC, nothing)
+BU_HTM_SPR1 (SET_TFIAR, "set_tfiar", MISC, nothing)
+BU_HTM_SPR0 (GET_TEXASR, "get_texasr", MISC, nothing)
+BU_HTM_SPR1 (SET_TEXASR, "set_texasr", MISC, nothing)
+BU_HTM_SPR0 (GET_TEXASRU, "get_texasru", MISC, nothing)
+BU_HTM_SPR1 (SET_TEXASRU, "set_texasru", MISC, nothing)
+
\f
/* 3 argument paired floating point builtins. */
BU_PAIRED_3 (MSUB, "msub", FP, fmsv2sf4)
RS6000_BTC_FP)
BU_SPECIAL_X (RS6000_BUILTIN_GET_TB, "__builtin_ppc_get_timebase",
- RS6000_BTM_ALWAYS, RS6000_BTC_MISC)
+ RS6000_BTM_ALWAYS, RS6000_BTC_MISC)
BU_SPECIAL_X (RS6000_BUILTIN_MFTB, "__builtin_ppc_mftb",
- RS6000_BTM_ALWAYS, RS6000_BTC_MISC)
+ RS6000_BTM_ALWAYS, RS6000_BTC_MISC)
/* Darwin CfString builtin. */
BU_SPECIAL_X (RS6000_BUILTIN_CFSTRING, "__builtin_cfstring", RS6000_BTM_ALWAYS,
}
if ((flags & OPTION_MASK_VSX) != 0)
rs6000_define_or_undefine_macro (define_p, "__VSX__");
+ if ((flags & OPTION_MASK_HTM) != 0)
+ rs6000_define_or_undefine_macro (define_p, "__HTM__");
if ((flags & OPTION_MASK_P8_VECTOR) != 0)
rs6000_define_or_undefine_macro (define_p, "__POWER8_VECTOR__");
if ((flags & OPTION_MASK_CRYPTO) != 0)
| OPTION_MASK_P8_VECTOR \
| OPTION_MASK_CRYPTO \
| OPTION_MASK_DIRECT_MOVE \
+ | OPTION_MASK_HTM \
| OPTION_MASK_QUAD_MEMORY)
#define POWERPC_7400_MASK (OPTION_MASK_PPC_GFXOPT | OPTION_MASK_ALTIVEC)
| OPTION_MASK_DIRECT_MOVE \
| OPTION_MASK_DLMZB \
| OPTION_MASK_FPRND \
+ | OPTION_MASK_HTM \
| OPTION_MASK_ISEL \
| OPTION_MASK_MFCRF \
| OPTION_MASK_MFPGPR \
#undef RS6000_BUILTIN_A
#undef RS6000_BUILTIN_D
#undef RS6000_BUILTIN_E
+#undef RS6000_BUILTIN_H
#undef RS6000_BUILTIN_P
#undef RS6000_BUILTIN_Q
#undef RS6000_BUILTIN_S
#define RS6000_BUILTIN_E(ENUM, NAME, MASK, ATTR, ICODE) \
{ NAME, ICODE, MASK, ATTR },
+#define RS6000_BUILTIN_H(ENUM, NAME, MASK, ATTR, ICODE) \
+ { NAME, ICODE, MASK, ATTR },
+
#define RS6000_BUILTIN_P(ENUM, NAME, MASK, ATTR, ICODE) \
{ NAME, ICODE, MASK, ATTR },
#undef RS6000_BUILTIN_A
#undef RS6000_BUILTIN_D
#undef RS6000_BUILTIN_E
+#undef RS6000_BUILTIN_H
#undef RS6000_BUILTIN_P
#undef RS6000_BUILTIN_Q
#undef RS6000_BUILTIN_S
static void paired_init_builtins (void);
static rtx paired_expand_predicate_builtin (enum insn_code, tree, rtx);
static void spe_init_builtins (void);
+static void htm_init_builtins (void);
static rtx spe_expand_predicate_builtin (enum insn_code, tree, rtx);
static rtx spe_expand_evsel_builtin (enum insn_code, tree, rtx);
static int rs6000_emit_int_cmove (rtx, rtx, rtx, rtx);
/* SPE registers. */
"spe_acc", "spefscr",
/* Soft frame pointer. */
- "sfp"
+ "sfp",
+ /* HTM SPR registers. */
+ "tfhar", "tfiar", "texasr"
};
#ifdef TARGET_REGNAMES
/* SPE registers. */
"spe_acc", "spefscr",
/* Soft frame pointer. */
- "sfp"
+ "sfp",
+ /* HTM SPR registers. */
+ "tfhar", "tfiar", "texasr"
};
#endif
rs6000_regno_regclass[VSCR_REGNO] = VRSAVE_REGS;
rs6000_regno_regclass[SPE_ACC_REGNO] = SPE_ACC_REGS;
rs6000_regno_regclass[SPEFSCR_REGNO] = SPEFSCR_REGS;
+ rs6000_regno_regclass[TFHAR_REGNO] = SPR_REGS;
+ rs6000_regno_regclass[TFIAR_REGNO] = SPR_REGS;
+ rs6000_regno_regclass[TEXASR_REGNO] = SPR_REGS;
rs6000_regno_regclass[ARG_POINTER_REGNUM] = BASE_REGS;
rs6000_regno_regclass[FRAME_POINTER_REGNUM] = BASE_REGS;
| ((TARGET_POPCNTD) ? RS6000_BTM_POPCNTD : 0)
| ((rs6000_cpu == PROCESSOR_CELL) ? RS6000_BTM_CELL : 0)
| ((TARGET_P8_VECTOR) ? RS6000_BTM_P8_VECTOR : 0)
- | ((TARGET_CRYPTO) ? RS6000_BTM_CRYPTO : 0));
+ | ((TARGET_CRYPTO) ? RS6000_BTM_CRYPTO : 0)
+ | ((TARGET_HTM) ? RS6000_BTM_HTM : 0));
}
/* Override command line options. Mostly we process the processor type and
#undef RS6000_BUILTIN_A
#undef RS6000_BUILTIN_D
#undef RS6000_BUILTIN_E
+#undef RS6000_BUILTIN_H
#undef RS6000_BUILTIN_P
#undef RS6000_BUILTIN_Q
#undef RS6000_BUILTIN_S
#define RS6000_BUILTIN_A(ENUM, NAME, MASK, ATTR, ICODE)
#define RS6000_BUILTIN_D(ENUM, NAME, MASK, ATTR, ICODE)
#define RS6000_BUILTIN_E(ENUM, NAME, MASK, ATTR, ICODE)
+#define RS6000_BUILTIN_H(ENUM, NAME, MASK, ATTR, ICODE)
#define RS6000_BUILTIN_P(ENUM, NAME, MASK, ATTR, ICODE)
#define RS6000_BUILTIN_Q(ENUM, NAME, MASK, ATTR, ICODE)
#define RS6000_BUILTIN_S(ENUM, NAME, MASK, ATTR, ICODE)
#undef RS6000_BUILTIN_A
#undef RS6000_BUILTIN_D
#undef RS6000_BUILTIN_E
+#undef RS6000_BUILTIN_H
#undef RS6000_BUILTIN_P
#undef RS6000_BUILTIN_Q
#undef RS6000_BUILTIN_S
{ MASK, ICODE, NAME, ENUM },
#define RS6000_BUILTIN_E(ENUM, NAME, MASK, ATTR, ICODE)
+#define RS6000_BUILTIN_H(ENUM, NAME, MASK, ATTR, ICODE)
#define RS6000_BUILTIN_P(ENUM, NAME, MASK, ATTR, ICODE)
#define RS6000_BUILTIN_Q(ENUM, NAME, MASK, ATTR, ICODE)
#define RS6000_BUILTIN_S(ENUM, NAME, MASK, ATTR, ICODE)
#undef RS6000_BUILTIN_A
#undef RS6000_BUILTIN_D
#undef RS6000_BUILTIN_E
+#undef RS6000_BUILTIN_H
#undef RS6000_BUILTIN_P
#undef RS6000_BUILTIN_Q
#undef RS6000_BUILTIN_S
#define RS6000_BUILTIN_A(ENUM, NAME, MASK, ATTR, ICODE)
#define RS6000_BUILTIN_D(ENUM, NAME, MASK, ATTR, ICODE)
#define RS6000_BUILTIN_E(ENUM, NAME, MASK, ATTR, ICODE)
+#define RS6000_BUILTIN_H(ENUM, NAME, MASK, ATTR, ICODE)
#define RS6000_BUILTIN_P(ENUM, NAME, MASK, ATTR, ICODE)
#define RS6000_BUILTIN_Q(ENUM, NAME, MASK, ATTR, ICODE)
#define RS6000_BUILTIN_S(ENUM, NAME, MASK, ATTR, ICODE)
#undef RS6000_BUILTIN_A
#undef RS6000_BUILTIN_D
#undef RS6000_BUILTIN_E
+#undef RS6000_BUILTIN_H
#undef RS6000_BUILTIN_P
#undef RS6000_BUILTIN_Q
#undef RS6000_BUILTIN_S
#define RS6000_BUILTIN_A(ENUM, NAME, MASK, ATTR, ICODE)
#define RS6000_BUILTIN_D(ENUM, NAME, MASK, ATTR, ICODE)
#define RS6000_BUILTIN_E(ENUM, NAME, MASK, ATTR, ICODE)
+#define RS6000_BUILTIN_H(ENUM, NAME, MASK, ATTR, ICODE)
#define RS6000_BUILTIN_P(ENUM, NAME, MASK, ATTR, ICODE) \
{ MASK, ICODE, NAME, ENUM },
#undef RS6000_BUILTIN_A
#undef RS6000_BUILTIN_D
#undef RS6000_BUILTIN_E
+#undef RS6000_BUILTIN_H
#undef RS6000_BUILTIN_P
#undef RS6000_BUILTIN_Q
#undef RS6000_BUILTIN_S
#define RS6000_BUILTIN_A(ENUM, NAME, MASK, ATTR, ICODE)
#define RS6000_BUILTIN_D(ENUM, NAME, MASK, ATTR, ICODE)
#define RS6000_BUILTIN_E(ENUM, NAME, MASK, ATTR, ICODE)
+#define RS6000_BUILTIN_H(ENUM, NAME, MASK, ATTR, ICODE)
#define RS6000_BUILTIN_P(ENUM, NAME, MASK, ATTR, ICODE)
#define RS6000_BUILTIN_Q(ENUM, NAME, MASK, ATTR, ICODE)
#define RS6000_BUILTIN_S(ENUM, NAME, MASK, ATTR, ICODE) \
#undef RS6000_BUILTIN_A
#undef RS6000_BUILTIN_D
#undef RS6000_BUILTIN_E
+#undef RS6000_BUILTIN_H
#undef RS6000_BUILTIN_P
#undef RS6000_BUILTIN_Q
#undef RS6000_BUILTIN_S
#define RS6000_BUILTIN_E(ENUM, NAME, MASK, ATTR, ICODE) \
{ MASK, ICODE, NAME, ENUM },
+#define RS6000_BUILTIN_H(ENUM, NAME, MASK, ATTR, ICODE)
#define RS6000_BUILTIN_P(ENUM, NAME, MASK, ATTR, ICODE)
#define RS6000_BUILTIN_Q(ENUM, NAME, MASK, ATTR, ICODE)
#define RS6000_BUILTIN_S(ENUM, NAME, MASK, ATTR, ICODE)
#undef RS6000_BUILTIN_A
#undef RS6000_BUILTIN_D
#undef RS6000_BUILTIN_E
+#undef RS6000_BUILTIN_H
#undef RS6000_BUILTIN_P
#undef RS6000_BUILTIN_Q
#undef RS6000_BUILTIN_S
#define RS6000_BUILTIN_A(ENUM, NAME, MASK, ATTR, ICODE)
#define RS6000_BUILTIN_D(ENUM, NAME, MASK, ATTR, ICODE)
#define RS6000_BUILTIN_E(ENUM, NAME, MASK, ATTR, ICODE)
+#define RS6000_BUILTIN_H(ENUM, NAME, MASK, ATTR, ICODE)
#define RS6000_BUILTIN_P(ENUM, NAME, MASK, ATTR, ICODE)
#define RS6000_BUILTIN_Q(ENUM, NAME, MASK, ATTR, ICODE) \
{ MASK, ICODE, NAME, ENUM },
#undef RS6000_BUILTIN_A
#undef RS6000_BUILTIN_D
#undef RS6000_BUILTIN_E
+#undef RS6000_BUILTIN_H
#undef RS6000_BUILTIN_P
#undef RS6000_BUILTIN_Q
#undef RS6000_BUILTIN_S
#define RS6000_BUILTIN_D(ENUM, NAME, MASK, ATTR, ICODE)
#define RS6000_BUILTIN_E(ENUM, NAME, MASK, ATTR, ICODE)
+#define RS6000_BUILTIN_H(ENUM, NAME, MASK, ATTR, ICODE)
#define RS6000_BUILTIN_P(ENUM, NAME, MASK, ATTR, ICODE)
#define RS6000_BUILTIN_Q(ENUM, NAME, MASK, ATTR, ICODE)
#define RS6000_BUILTIN_S(ENUM, NAME, MASK, ATTR, ICODE)
#undef RS6000_BUILTIN_2
#undef RS6000_BUILTIN_3
#undef RS6000_BUILTIN_A
-#undef RS6000_BUILTIN_E
#undef RS6000_BUILTIN_D
+#undef RS6000_BUILTIN_E
+#undef RS6000_BUILTIN_H
#undef RS6000_BUILTIN_P
#undef RS6000_BUILTIN_Q
#undef RS6000_BUILTIN_S
#define RS6000_BUILTIN_A(ENUM, NAME, MASK, ATTR, ICODE)
#define RS6000_BUILTIN_D(ENUM, NAME, MASK, ATTR, ICODE)
#define RS6000_BUILTIN_E(ENUM, NAME, MASK, ATTR, ICODE)
+#define RS6000_BUILTIN_H(ENUM, NAME, MASK, ATTR, ICODE)
#define RS6000_BUILTIN_P(ENUM, NAME, MASK, ATTR, ICODE)
#define RS6000_BUILTIN_Q(ENUM, NAME, MASK, ATTR, ICODE)
#define RS6000_BUILTIN_S(ENUM, NAME, MASK, ATTR, ICODE)
#include "rs6000-builtin.def"
};
+/* HTM builtins. */
#undef RS6000_BUILTIN_1
#undef RS6000_BUILTIN_2
#undef RS6000_BUILTIN_3
#undef RS6000_BUILTIN_A
#undef RS6000_BUILTIN_D
#undef RS6000_BUILTIN_E
+#undef RS6000_BUILTIN_H
#undef RS6000_BUILTIN_P
#undef RS6000_BUILTIN_Q
#undef RS6000_BUILTIN_S
#undef RS6000_BUILTIN_X
+#define RS6000_BUILTIN_1(ENUM, NAME, MASK, ATTR, ICODE)
+#define RS6000_BUILTIN_2(ENUM, NAME, MASK, ATTR, ICODE)
+#define RS6000_BUILTIN_3(ENUM, NAME, MASK, ATTR, ICODE)
+#define RS6000_BUILTIN_A(ENUM, NAME, MASK, ATTR, ICODE)
+#define RS6000_BUILTIN_D(ENUM, NAME, MASK, ATTR, ICODE)
+#define RS6000_BUILTIN_E(ENUM, NAME, MASK, ATTR, ICODE)
+#define RS6000_BUILTIN_H(ENUM, NAME, MASK, ATTR, ICODE) \
+ { MASK, ICODE, NAME, ENUM },
+
+#define RS6000_BUILTIN_P(ENUM, NAME, MASK, ATTR, ICODE)
+#define RS6000_BUILTIN_Q(ENUM, NAME, MASK, ATTR, ICODE)
+#define RS6000_BUILTIN_S(ENUM, NAME, MASK, ATTR, ICODE)
+#define RS6000_BUILTIN_X(ENUM, NAME, MASK, ATTR, ICODE)
+
+static const struct builtin_description bdesc_htm[] =
+{
+#include "rs6000-builtin.def"
+};
+
+#undef RS6000_BUILTIN_1
+#undef RS6000_BUILTIN_2
+#undef RS6000_BUILTIN_3
+#undef RS6000_BUILTIN_A
+#undef RS6000_BUILTIN_D
+#undef RS6000_BUILTIN_E
+#undef RS6000_BUILTIN_H
+#undef RS6000_BUILTIN_P
+#undef RS6000_BUILTIN_Q
+#undef RS6000_BUILTIN_S
+
/* Return true if a builtin function is overloaded. */
bool
rs6000_overloaded_builtin_p (enum rs6000_builtins fncode)
return NULL_RTX;
}
+/* Return the appropriate SPR number associated with the given builtin. */
+static inline HOST_WIDE_INT
+htm_spr_num (enum rs6000_builtins code)
+{
+ if (code == HTM_BUILTIN_GET_TFHAR
+ || code == HTM_BUILTIN_SET_TFHAR)
+ return TFHAR_SPR;
+ else if (code == HTM_BUILTIN_GET_TFIAR
+ || code == HTM_BUILTIN_SET_TFIAR)
+ return TFIAR_SPR;
+ else if (code == HTM_BUILTIN_GET_TEXASR
+ || code == HTM_BUILTIN_SET_TEXASR)
+ return TEXASR_SPR;
+ gcc_assert (code == HTM_BUILTIN_GET_TEXASRU
+ || code == HTM_BUILTIN_SET_TEXASRU);
+ return TEXASRU_SPR;
+}
+
+/* Return the appropriate SPR regno associated with the given builtin. */
+static inline HOST_WIDE_INT
+htm_spr_regno (enum rs6000_builtins code)
+{
+ if (code == HTM_BUILTIN_GET_TFHAR
+ || code == HTM_BUILTIN_SET_TFHAR)
+ return TFHAR_REGNO;
+ else if (code == HTM_BUILTIN_GET_TFIAR
+ || code == HTM_BUILTIN_SET_TFIAR)
+ return TFIAR_REGNO;
+ gcc_assert (code == HTM_BUILTIN_GET_TEXASR
+ || code == HTM_BUILTIN_SET_TEXASR
+ || code == HTM_BUILTIN_GET_TEXASRU
+ || code == HTM_BUILTIN_SET_TEXASRU);
+ return TEXASR_REGNO;
+}
+
+/* Return the correct ICODE value depending on whether we are
+ setting or reading the HTM SPRs. */
+static inline enum insn_code
+rs6000_htm_spr_icode (bool nonvoid)
+{
+ if (nonvoid)
+ return (TARGET_64BIT) ? CODE_FOR_htm_mfspr_di : CODE_FOR_htm_mfspr_si;
+ else
+ return (TARGET_64BIT) ? CODE_FOR_htm_mtspr_di : CODE_FOR_htm_mtspr_si;
+}
+
+/* Expand the HTM builtin in EXP and store the result in TARGET.
+ Store true in *EXPANDEDP if we found a builtin to expand. */
+static rtx
+htm_expand_builtin (tree exp, rtx target, bool * expandedp)
+{
+ tree fndecl = TREE_OPERAND (CALL_EXPR_FN (exp), 0);
+ bool nonvoid = TREE_TYPE (TREE_TYPE (fndecl)) != void_type_node;
+ enum rs6000_builtins fcode = (enum rs6000_builtins) DECL_FUNCTION_CODE (fndecl);
+ const struct builtin_description *d;
+ size_t i;
+
+ *expandedp = false;
+
+ /* Expand the HTM builtins. */
+ d = bdesc_htm;
+ for (i = 0; i < ARRAY_SIZE (bdesc_htm); i++, d++)
+ if (d->code == fcode)
+ {
+ rtx op[MAX_HTM_OPERANDS], pat;
+ int nopnds = 0;
+ tree arg;
+ call_expr_arg_iterator iter;
+ unsigned attr = rs6000_builtin_info[fcode].attr;
+ enum insn_code icode = d->icode;
+
+ if (attr & RS6000_BTC_SPR)
+ icode = rs6000_htm_spr_icode (nonvoid);
+
+ if (nonvoid)
+ {
+ enum machine_mode tmode = insn_data[icode].operand[0].mode;
+ if (!target
+ || GET_MODE (target) != tmode
+ || !(*insn_data[icode].operand[0].predicate) (target, tmode))
+ target = gen_reg_rtx (tmode);
+ op[nopnds++] = target;
+ }
+
+ FOR_EACH_CALL_EXPR_ARG (arg, iter, exp)
+ {
+ const struct insn_operand_data *insn_op;
+
+ if (arg == error_mark_node || nopnds >= MAX_HTM_OPERANDS)
+ return NULL_RTX;
+
+ insn_op = &insn_data[icode].operand[nopnds];
+
+ op[nopnds] = expand_normal (arg);
+
+ if (!(*insn_op->predicate) (op[nopnds], insn_op->mode))
+ {
+ if (!strcmp (insn_op->constraint, "n"))
+ {
+ int arg_num = (nonvoid) ? nopnds : nopnds + 1;
+ if (!CONST_INT_P (op[nopnds]))
+ error ("argument %d must be an unsigned literal", arg_num);
+ else
+ error ("argument %d is an unsigned literal that is "
+ "out of range", arg_num);
+ return const0_rtx;
+ }
+ op[nopnds] = copy_to_mode_reg (insn_op->mode, op[nopnds]);
+ }
+
+ nopnds++;
+ }
+
+ /* Handle the builtins for extended mnemonics. These accept
+ no arguments, but map to builtins that take arguments. */
+ switch (fcode)
+ {
+ case HTM_BUILTIN_TENDALL: /* Alias for: tend. 1 */
+ case HTM_BUILTIN_TRESUME: /* Alias for: tsr. 1 */
+ op[nopnds++] = GEN_INT (1);
+#ifdef ENABLE_CHECKING
+ attr |= RS6000_BTC_UNARY;
+#endif
+ break;
+ case HTM_BUILTIN_TSUSPEND: /* Alias for: tsr. 0 */
+ op[nopnds++] = GEN_INT (0);
+#ifdef ENABLE_CHECKING
+ attr |= RS6000_BTC_UNARY;
+#endif
+ break;
+ default:
+ break;
+ }
+
+ /* If this builtin accesses SPRs, then pass in the appropriate
+ SPR number and SPR regno as the last two operands. */
+ if (attr & RS6000_BTC_SPR)
+ {
+ op[nopnds++] = gen_rtx_CONST_INT (Pmode, htm_spr_num (fcode));
+ op[nopnds++] = gen_rtx_REG (Pmode, htm_spr_regno (fcode));
+ }
+
+#ifdef ENABLE_CHECKING
+ int expected_nopnds = 0;
+ if ((attr & RS6000_BTC_TYPE_MASK) == RS6000_BTC_UNARY)
+ expected_nopnds = 1;
+ else if ((attr & RS6000_BTC_TYPE_MASK) == RS6000_BTC_BINARY)
+ expected_nopnds = 2;
+ else if ((attr & RS6000_BTC_TYPE_MASK) == RS6000_BTC_TERNARY)
+ expected_nopnds = 3;
+ if (!(attr & RS6000_BTC_VOID))
+ expected_nopnds += 1;
+ if (attr & RS6000_BTC_SPR)
+ expected_nopnds += 2;
+
+ gcc_assert (nopnds == expected_nopnds && nopnds <= MAX_HTM_OPERANDS);
+#endif
+
+ switch (nopnds)
+ {
+ case 0:
+ pat = GEN_FCN (icode) (NULL_RTX);
+ break;
+ case 1:
+ pat = GEN_FCN (icode) (op[0]);
+ break;
+ case 2:
+ pat = GEN_FCN (icode) (op[0], op[1]);
+ break;
+ case 3:
+ pat = GEN_FCN (icode) (op[0], op[1], op[2]);
+ break;
+ case 4:
+ pat = GEN_FCN (icode) (op[0], op[1], op[2], op[3]);
+ break;
+ default:
+ gcc_unreachable ();
+ }
+ if (!pat)
+ return NULL_RTX;
+ emit_insn (pat);
+
+ *expandedp = true;
+ if (nonvoid)
+ return target;
+ return const0_rtx;
+ }
+
+ return NULL_RTX;
+}
+
static rtx
rs6000_expand_ternop_builtin (enum insn_code icode, tree exp, rtx target)
{
error ("Builtin function %s is only valid for the cell processor", name);
else if ((fnmask & RS6000_BTM_VSX) != 0)
error ("Builtin function %s requires the -mvsx option", name);
+ else if ((fnmask & RS6000_BTM_HTM) != 0)
+ error ("Builtin function %s requires the -mhtm option", name);
else if ((fnmask & RS6000_BTM_ALTIVEC) != 0)
error ("Builtin function %s requires the -maltivec option", name);
else if ((fnmask & RS6000_BTM_PAIRED) != 0)
{
ret = paired_expand_builtin (exp, target, &success);
+ if (success)
+ return ret;
+ }
+ if (TARGET_HTM)
+ {
+ ret = htm_expand_builtin (exp, target, &success);
+
if (success)
return ret;
}
spe_init_builtins ();
if (TARGET_EXTRA_BUILTINS)
altivec_init_builtins ();
+ if (TARGET_HTM)
+ htm_init_builtins ();
+
if (TARGET_EXTRA_BUILTINS || TARGET_SPE || TARGET_PAIRED_FLOAT)
rs6000_common_init_builtins ();
def_builtin ("__builtin_vec_ext_v2di", ftype, VSX_BUILTIN_VEC_EXT_V2DI);
}
+static void
+htm_init_builtins (void)
+{
+ HOST_WIDE_INT builtin_mask = rs6000_builtin_mask;
+ const struct builtin_description *d;
+ size_t i;
+
+ d = bdesc_htm;
+ for (i = 0; i < ARRAY_SIZE (bdesc_htm); i++, d++)
+ {
+ tree op[MAX_HTM_OPERANDS], type;
+ HOST_WIDE_INT mask = d->mask;
+ unsigned attr = rs6000_builtin_info[d->code].attr;
+ bool void_func = (attr & RS6000_BTC_VOID);
+ int attr_args = (attr & RS6000_BTC_TYPE_MASK);
+ int nopnds = 0;
+ tree argtype = (attr & RS6000_BTC_SPR) ? long_unsigned_type_node
+ : unsigned_type_node;
+
+ if ((mask & builtin_mask) != mask)
+ {
+ if (TARGET_DEBUG_BUILTIN)
+ fprintf (stderr, "htm_builtin, skip binary %s\n", d->name);
+ continue;
+ }
+
+ if (d->name == 0)
+ {
+ if (TARGET_DEBUG_BUILTIN)
+ fprintf (stderr, "htm_builtin, bdesc_htm[%ld] no name\n",
+ (long unsigned) i);
+ continue;
+ }
+
+ op[nopnds++] = (void_func) ? void_type_node : argtype;
+
+ if (attr_args == RS6000_BTC_UNARY)
+ op[nopnds++] = argtype;
+ else if (attr_args == RS6000_BTC_BINARY)
+ {
+ op[nopnds++] = argtype;
+ op[nopnds++] = argtype;
+ }
+ else if (attr_args == RS6000_BTC_TERNARY)
+ {
+ op[nopnds++] = argtype;
+ op[nopnds++] = argtype;
+ op[nopnds++] = argtype;
+ }
+
+ switch (nopnds)
+ {
+ case 1:
+ type = build_function_type_list (op[0], NULL_TREE);
+ break;
+ case 2:
+ type = build_function_type_list (op[0], op[1], NULL_TREE);
+ break;
+ case 3:
+ type = build_function_type_list (op[0], op[1], op[2], NULL_TREE);
+ break;
+ case 4:
+ type = build_function_type_list (op[0], op[1], op[2], op[3],
+ NULL_TREE);
+ break;
+ default:
+ gcc_unreachable ();
+ }
+
+ def_builtin (d->name, type, d->code);
+ }
+}
+
/* Hash function for builtin functions with up to 3 arguments and a return
type. */
static unsigned
{ "dlmzb", OPTION_MASK_DLMZB, false, true },
{ "fprnd", OPTION_MASK_FPRND, false, true },
{ "hard-dfp", OPTION_MASK_DFP, false, true },
+ { "htm", OPTION_MASK_HTM, false, true },
{ "isel", OPTION_MASK_ISEL, false, true },
{ "mfcrf", OPTION_MASK_MFCRF, false, true },
{ "mfpgpr", OPTION_MASK_MFPGPR, false, true },
{ "cell", RS6000_BTM_CELL, false, false },
{ "power8-vector", RS6000_BTM_P8_VECTOR, false, false },
{ "crypto", RS6000_BTM_CRYPTO, false, false },
+ { "htm", RS6000_BTM_HTM, false, false },
};
/* Option variables that we want to support inside attribute((target)) and
%{mcpu=e6500: -me6500} \
%{maltivec: -maltivec} \
%{mvsx: -mvsx %{!maltivec: -maltivec} %{!mcpu*: %(asm_cpu_power7)}} \
-%{mpower8-vector|mcrypto|mdirect-move: %{!mcpu*: %(asm_cpu_power8)}} \
+%{mpower8-vector|mcrypto|mdirect-move|mhtm: %{!mcpu*: %(asm_cpu_power8)}} \
-many"
#define CPP_DEFAULT_SPEC ""
#ifndef HAVE_AS_POWER8
#undef TARGET_DIRECT_MOVE
#undef TARGET_CRYPTO
+#undef TARGET_HTM
#undef TARGET_P8_VECTOR
#define TARGET_DIRECT_MOVE 0
#define TARGET_CRYPTO 0
+#define TARGET_HTM 0
#define TARGET_P8_VECTOR 0
#endif
#define MASK_FPRND OPTION_MASK_FPRND
#define MASK_P8_FUSION OPTION_MASK_P8_FUSION
#define MASK_HARD_FLOAT OPTION_MASK_HARD_FLOAT
+#define MASK_HTM OPTION_MASK_HTM
#define MASK_ISEL OPTION_MASK_ISEL
#define MASK_MFCRF OPTION_MASK_MFCRF
#define MASK_MFPGPR OPTION_MASK_MFPGPR
in inline functions.
Another pseudo (not included in DWARF_FRAME_REGISTERS) is soft frame
- pointer, which is eventually eliminated in favor of SP or FP. */
+ pointer, which is eventually eliminated in favor of SP or FP.
-#define FIRST_PSEUDO_REGISTER 114
+ The 3 HTM registers aren't also included in DWARF_FRAME_REGISTERS. */
+
+#define FIRST_PSEUDO_REGISTER 117
/* This must be included for pre gcc 3.0 glibc compatibility. */
#define PRE_GCC3_DWARF_FRAME_REGISTERS 77
/* Add 32 dwarf columns for synthetic SPE registers. */
-#define DWARF_FRAME_REGISTERS ((FIRST_PSEUDO_REGISTER - 1) + 32)
+#define DWARF_FRAME_REGISTERS ((FIRST_PSEUDO_REGISTER - 4) + 32)
/* The SPE has an additional 32 synthetic registers, with DWARF debug
info numbering for these registers starting at 1200. While eh_frame
We must map them here to avoid huge unwinder tables mostly consisting
of unused space. */
#define DWARF_REG_TO_UNWIND_COLUMN(r) \
- ((r) > 1200 ? ((r) - 1200 + FIRST_PSEUDO_REGISTER - 1) : (r))
+ ((r) > 1200 ? ((r) - 1200 + (DWARF_FRAME_REGISTERS - 32)) : (r))
/* Use standard DWARF numbering for DWARF debugging information. */
#define DBX_REGISTER_NUMBER(REGNO) rs6000_dbx_register_number (REGNO)
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, \
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, \
1, 1 \
- , 1, 1, 1 \
+ , 1, 1, 1, 1, 1, 1 \
}
/* 1 for registers not available across function calls.
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, \
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, \
1, 1 \
- , 1, 1, 1 \
+ , 1, 1, 1, 1, 1, 1 \
}
/* Like `CALL_USED_REGISTERS' except this macro doesn't require that
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, \
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, \
0, 0 \
- , 0, 0, 0 \
+ , 0, 0, 0, 0, 0, 0 \
}
#define TOTAL_ALTIVEC_REGS (LAST_ALTIVEC_REGNO - FIRST_ALTIVEC_REGNO + 1)
vrsave, vscr (fixed)
spe_acc, spefscr (fixed)
sfp (fixed)
+ tfhar (fixed)
+ tfiar (fixed)
+ texasr (fixed)
*/
#if FIXED_R2 == 1
96, 95, 94, 93, 92, 91, \
108, 107, 106, 105, 104, 103, 102, 101, 100, 99, 98, 97, \
109, 110, \
- 111, 112, 113 \
+ 111, 112, 113, 114, 115, 116 \
}
/* True if register is floating-point. */
VSCR_REGS,
SPE_ACC_REGS,
SPEFSCR_REGS,
+ SPR_REGS,
NON_SPECIAL_REGS,
LINK_REGS,
CTR_REGS,
"VSCR_REGS", \
"SPE_ACC_REGS", \
"SPEFSCR_REGS", \
+ "SPR_REGS", \
"NON_SPECIAL_REGS", \
"LINK_REGS", \
"CTR_REGS", \
{ 0x00000000, 0x00000000, 0x00000000, 0x00004000 }, /* VSCR_REGS */ \
{ 0x00000000, 0x00000000, 0x00000000, 0x00008000 }, /* SPE_ACC_REGS */ \
{ 0x00000000, 0x00000000, 0x00000000, 0x00010000 }, /* SPEFSCR_REGS */ \
+ { 0x00000000, 0x00000000, 0x00000000, 0x00040000 }, /* SPR_REGS */ \
{ 0xffffffff, 0xffffffff, 0x00000008, 0x00020000 }, /* NON_SPECIAL_REGS */ \
{ 0x00000000, 0x00000000, 0x00000002, 0x00000000 }, /* LINK_REGS */ \
{ 0x00000000, 0x00000000, 0x00000004, 0x00000000 }, /* CTR_REGS */ \
{ 0x00000000, 0x00000000, 0x00000ff0, 0x00000000 }, /* CR_REGS */ \
{ 0xffffffff, 0x00000000, 0x00000ffe, 0x00020000 }, /* NON_FLOAT_REGS */ \
{ 0x00000000, 0x00000000, 0x00001000, 0x00000000 }, /* CA_REGS */ \
- { 0xffffffff, 0xffffffff, 0xfffffffe, 0x0003ffff } /* ALL_REGS */ \
+ { 0xffffffff, 0xffffffff, 0xfffffffe, 0x0007ffff } /* ALL_REGS */ \
}
/* The same information, inverted:
&rs6000_reg_names[111][0], /* spe_acc */ \
&rs6000_reg_names[112][0], /* spefscr */ \
&rs6000_reg_names[113][0], /* sfp */ \
+ &rs6000_reg_names[114][0], /* tfhar */ \
+ &rs6000_reg_names[115][0], /* tfiar */ \
+ &rs6000_reg_names[116][0], /* texasr */ \
}
/* Table of additional register names to use in user input. */
{"vs48", 93}, {"vs49", 94}, {"vs50", 95}, {"vs51", 96}, \
{"vs52", 97}, {"vs53", 98}, {"vs54", 99}, {"vs55", 100}, \
{"vs56", 101},{"vs57", 102},{"vs58", 103},{"vs59", 104}, \
- {"vs60", 105},{"vs61", 106},{"vs62", 107},{"vs63", 108} }
+ {"vs60", 105},{"vs61", 106},{"vs62", 107},{"vs63", 108}, \
+ /* Transactional Memory Facility (HTM) Registers. */ \
+ {"tfhar", 114}, {"tfiar", 115}, {"texasr", 116} }
/* This is how to output an element of a case-vector that is relative. */
#define RS6000_BTC_ATTR_MASK 0x00000700 /* Mask of the attributes. */
/* Miscellaneous information. */
-#define RS6000_BTC_OVERLOADED 0x4000000 /* function is overloaded. */
+#define RS6000_BTC_SPR 0x01000000 /* function references SPRs. */
+#define RS6000_BTC_VOID 0x02000000 /* function has no return value. */
+#define RS6000_BTC_OVERLOADED 0x04000000 /* function is overloaded. */
+#define RS6000_BTC_32BIT 0x08000000 /* function references SPRs. */
+#define RS6000_BTC_64BIT 0x10000000 /* function references SPRs. */
+#define RS6000_BTC_MISC_MASK 0x1f000000 /* Mask of the misc info. */
/* Convenience macros to document the instruction type. */
#define RS6000_BTC_MEM RS6000_BTC_MISC /* load/store touches mem. */
#define RS6000_BTM_VSX MASK_VSX /* VSX (vector/scalar). */
#define RS6000_BTM_P8_VECTOR MASK_P8_VECTOR /* ISA 2.07 vector. */
#define RS6000_BTM_CRYPTO MASK_CRYPTO /* crypto funcs. */
+#define RS6000_BTM_HTM MASK_HTM /* hardware TM funcs. */
#define RS6000_BTM_SPE MASK_STRING /* E500 */
#define RS6000_BTM_PAIRED MASK_MULHW /* 750CL paired insns. */
#define RS6000_BTM_FRE MASK_POPCNTB /* FRE instruction. */
| RS6000_BTM_FRES \
| RS6000_BTM_FRSQRTE \
| RS6000_BTM_FRSQRTES \
+ | RS6000_BTM_HTM \
| RS6000_BTM_POPCNTD \
| RS6000_BTM_CELL)
#undef RS6000_BUILTIN_A
#undef RS6000_BUILTIN_D
#undef RS6000_BUILTIN_E
+#undef RS6000_BUILTIN_H
#undef RS6000_BUILTIN_P
#undef RS6000_BUILTIN_Q
#undef RS6000_BUILTIN_S
#define RS6000_BUILTIN_A(ENUM, NAME, MASK, ATTR, ICODE) ENUM,
#define RS6000_BUILTIN_D(ENUM, NAME, MASK, ATTR, ICODE) ENUM,
#define RS6000_BUILTIN_E(ENUM, NAME, MASK, ATTR, ICODE) ENUM,
+#define RS6000_BUILTIN_H(ENUM, NAME, MASK, ATTR, ICODE) ENUM,
#define RS6000_BUILTIN_P(ENUM, NAME, MASK, ATTR, ICODE) ENUM,
#define RS6000_BUILTIN_Q(ENUM, NAME, MASK, ATTR, ICODE) ENUM,
#define RS6000_BUILTIN_S(ENUM, NAME, MASK, ATTR, ICODE) ENUM,
#undef RS6000_BUILTIN_A
#undef RS6000_BUILTIN_D
#undef RS6000_BUILTIN_E
+#undef RS6000_BUILTIN_H
#undef RS6000_BUILTIN_P
#undef RS6000_BUILTIN_Q
#undef RS6000_BUILTIN_S
(SPE_ACC_REGNO 111)
(SPEFSCR_REGNO 112)
(FRAME_POINTER_REGNUM 113)
+ (TFHAR_REGNO 114)
+ (TFIAR_REGNO 115)
+ (TEXASR_REGNO 116)
; ABI defined stack offsets for storing the TOC pointer with AIX calls.
(TOC_SAVE_OFFSET_32BIT 20)
\f
;; Define an insn type attribute. This is used in function unit delay
;; computations.
-(define_attr "type" "integer,two,three,load,load_ext,load_ext_u,load_ext_ux,load_ux,load_u,store,store_ux,store_u,fpload,fpload_ux,fpload_u,fpstore,fpstore_ux,fpstore_u,vecload,vecstore,imul,imul2,imul3,lmul,idiv,ldiv,insert_word,branch,cmp,fast_compare,compare,var_delayed_compare,delayed_compare,imul_compare,lmul_compare,fpcompare,cr_logical,delayed_cr,mfcr,mfcrf,mtcr,mfjmpr,mtjmpr,fp,fpsimple,dmul,sdiv,ddiv,ssqrt,dsqrt,jmpreg,brinc,vecsimple,veccomplex,vecdiv,veccmp,veccmpsimple,vecperm,vecfloat,vecfdiv,vecdouble,isync,sync,load_l,store_c,shift,trap,insert_dword,var_shift_rotate,cntlz,exts,mffgpr,mftgpr,isel,popcnt,crypto"
+(define_attr "type" "integer,two,three,load,load_ext,load_ext_u,load_ext_ux,load_ux,load_u,store,store_ux,store_u,fpload,fpload_ux,fpload_u,fpstore,fpstore_ux,fpstore_u,vecload,vecstore,imul,imul2,imul3,lmul,idiv,ldiv,insert_word,branch,cmp,fast_compare,compare,var_delayed_compare,delayed_compare,imul_compare,lmul_compare,fpcompare,cr_logical,delayed_cr,mfcr,mfcrf,mtcr,mfjmpr,mtjmpr,fp,fpsimple,dmul,sdiv,ddiv,ssqrt,dsqrt,jmpreg,brinc,vecsimple,veccomplex,vecdiv,veccmp,veccmpsimple,vecperm,vecfloat,vecfdiv,vecdouble,isync,sync,load_l,store_c,shift,trap,insert_dword,var_shift_rotate,cntlz,exts,mffgpr,mftgpr,isel,popcnt,crypto,htm"
(const_string "integer"))
;; Define floating point instruction sub-types for use with Xfpu.md
(include "dfp.md")
(include "paired.md")
(include "crypto.md")
+(include "htm.md")
Target Report Mask(DIRECT_MOVE) Var(rs6000_isa_flags)
Use ISA 2.07 direct move between GPR & VSX register instructions
+mhtm
+Target Report Mask(HTM) Var(rs6000_isa_flags)
+Use ISA 2.07 transactional memory (HTM) instructions
+
mquad-memory
Target Report Mask(QUAD_MEMORY) Var(rs6000_isa_flags)
Generate the quad word memory instructions (lq/stq/lqarx/stqcx).
$(srcdir)/config/rs6000/vsx.md \
$(srcdir)/config/rs6000/altivec.md \
$(srcdir)/config/rs6000/crypto.md \
+ $(srcdir)/config/rs6000/htm.md \
$(srcdir)/config/rs6000/spe.md \
$(srcdir)/config/rs6000/dfp.md \
$(srcdir)/config/rs6000/paired.md
* picoChip Built-in Functions::
* PowerPC Built-in Functions::
* PowerPC AltiVec/VSX Built-in Functions::
+* PowerPC Hardware Transactional Memory Built-in Functions::
* RX Built-in Functions::
* S/390 System z Built-in Functions::
* SH Built-in Functions::
integer that is 0 or 1. The third argument to these builtin functions
must be a constant integer in the range of 0 to 15.
+@node PowerPC Hardware Transactional Memory Built-in Functions
+@subsection PowerPC Hardware Transactional Memory Built-in Functions
+GCC provides two interfaces for accessing the Hardware Transactional
+Memory (HTM) instructions available on some of the PowerPC family
+of prcoessors (eg, POWER8). The two interfaces come in a low level
+interface, consisting of built-in functions specific to PowerPC and a
+higher level interface consisting of inline functions that are common
+between PowerPC and S/390.
+
+@subsubsection PowerPC HTM Low Level Built-in Functions
+
+The following low level built-in functions are available with
+@option{-mhtm} or @option{-mcpu=CPU} where CPU is `power8' or later.
+They all generate the machine instruction that is part of the name.
+
+The HTM built-ins return true or false depending on their success and
+their arguments match exactly the type and order of the associated
+hardware instruction's operands. Refer to the ISA manual for a
+description of each instruction's operands.
+
+@smallexample
+unsigned int __builtin_tbegin (unsigned int)
+unsigned int __builtin_tend (unsigned int)
+
+unsigned int __builtin_tabort (unsigned int)
+unsigned int __builtin_tabortdc (unsigned int, unsigned int, unsigned int)
+unsigned int __builtin_tabortdci (unsigned int, unsigned int, int)
+unsigned int __builtin_tabortwc (unsigned int, unsigned int, unsigned int)
+unsigned int __builtin_tabortwci (unsigned int, unsigned int, int)
+
+unsigned int __builtin_tcheck (unsigned int)
+unsigned int __builtin_treclaim (unsigned int)
+unsigned int __builtin_trechkpt (void)
+unsigned int __builtin_tsr (unsigned int)
+@end smallexample
+
+In addition to the above HTM built-ins, we have added built-ins for
+some common extended mnemonics of the HTM instructions:
+
+@smallexample
+unsigned int __builtin_tendall (void)
+unsigned int __builtin_tresume (void)
+unsigned int __builtin_tsuspend (void)
+@end smallexample
+
+The following set of built-in functions are available to gain access
+to the HTM specific special purpose registers.
+
+@smallexample
+unsigned long __builtin_get_texasr (void)
+unsigned long __builtin_get_texasru (void)
+unsigned long __builtin_get_tfhar (void)
+unsigned long __builtin_get_tfiar (void)
+
+void __builtin_set_texasr (unsigned long);
+void __builtin_set_texasru (unsigned long);
+void __builtin_set_tfhar (unsigned long);
+void __builtin_set_tfiar (unsigned long);
+@end smallexample
+
+Example usage of these low level built-in functions may look like:
+
+@smallexample
+#include <htmintrin.h>
+
+int num_retries = 10;
+
+while (1)
+ @{
+ if (__builtin_tbegin (0))
+ @{
+ /* Transaction State Initiated. */
+ if (is_locked (lock))
+ __builtin_tabort (0);
+ ... transaction code...
+ __builtin_tend (0);
+ break;
+ @}
+ else
+ @{
+ /* Transaction State Failed. Use locks if the transaction
+ failure is "persistent" or we've tried too many times. */
+ if (num_retries-- <= 0
+ || _TEXASRU_FAILURE_PERSISTENT (__builtin_get_texasru ()))
+ @{
+ acquire_lock (lock);
+ ... non transactional fallback path...
+ release_lock (lock);
+ break;
+ @}
+ @}
+ @}
+@end smallexample
+
+One final built-in function has been added that returns the value of
+the 2-bit Transaction State field of the Machine Status Register (MSR)
+as stored in @code{CR0}.
+
+@smallexample
+unsigned long __builtin_ttest (void)
+@end smallexample
+
+This built-in can be used to determine the current transaction state
+using the following code example:
+
+@smallexample
+#include <htmintrin.h>
+
+unsigned char tx_state = _HTM_STATE (__builtin_ttest ());
+
+if (tx_state == _HTM_TRANSACTIONAL)
+ @{
+ /* Code to use in transactional state. */
+ @}
+else if (tx_state == _HTM_NONTRANSACTIONAL)
+ @{
+ /* Code to use in non-transactional state. */
+ @}
+else if (tx_state == _HTM_SUSPENDED)
+ @{
+ /* Code to use in transaction suspended state. */
+ @}
+@end smallexample
+
+@subsubsection PowerPC HTM High Level Inline Functions
+
+The following high level HTM interface is made available by including
+@code{<htmxlintrin.h>} and using @option{-mhtm} or @option{-mcpu=CPU}
+where CPU is `power8' or later. This interface is common between PowerPC
+and S/390, allowing users to write one HTM source implementation that
+can be compiled and executed on either system.
+
+@smallexample
+long __TM_simple_begin (void)
+long __TM_begin (void* const TM_buff)
+long __TM_end (void)
+void __TM_abort (void)
+void __TM_named_abort (unsigned char const code)
+void __TM_resume (void)
+void __TM_suspend (void)
+
+long __TM_is_user_abort (void* const TM_buff)
+long __TM_is_named_user_abort (void* const TM_buff, unsigned char *code)
+long __TM_is_illegal (void* const TM_buff)
+long __TM_is_footprint_exceeded (void* const TM_buff)
+long __TM_nesting_depth (void* const TM_buff)
+long __TM_is_nested_too_deep(void* const TM_buff)
+long __TM_is_conflict(void* const TM_buff)
+long __TM_is_failure_persistent(void* const TM_buff)
+long __TM_failure_address(void* const TM_buff)
+long long __TM_failure_code(void* const TM_buff)
+@end smallexample
+
+Using these common set of HTM inline functions, we can create
+a more portable version of the HTM example in the previous
+section that will work on either PowerPC or S/390:
+
+@smallexample
+#include <htmxlintrin.h>
+
+int num_retries = 10;
+TM_buff_type TM_buff;
+
+while (1)
+ @{
+ if (__TM_begin (TM_buff))
+ @{
+ /* Transaction State Initiated. */
+ if (is_locked (lock))
+ __TM_abort ();
+ ... transaction code...
+ __TM_end ();
+ break;
+ @}
+ else
+ @{
+ /* Transaction State Failed. Use locks if the transaction
+ failure is "persistent" or we've tried too many times. */
+ if (num_retries-- <= 0
+ || __TM_is_failure_persistent (TM_buff))
+ @{
+ acquire_lock (lock);
+ ... non transactional fallback path...
+ release_lock (lock);
+ break;
+ @}
+ @}
+ @}
+@end smallexample
+
@node RX Built-in Functions
@subsection RX Built-in Functions
GCC supports some of the RX instructions which cannot be expressed in
+2014-04-04 Bill Schmidt <wschmidt@linux.vnet.ibm.com>
+
+ Power8 HTM Support
+ Backport from mainline
+ * lib/target-supports.exp (check_effective_target_powerpc_htm_ok): New
+ function to test if HTM is available.
+ * gcc.target/powerpc/htm-xl-intrin-1.c: New test.
+ * gcc.target/powerpc/htm-builtin-1.c: New test.
+
2014-04-04 Bill Schmidt <wschmidt@linux.vnet.ibm.com>
Power8 Base Support
--- /dev/null
+/* { dg-do compile { target { powerpc*-*-* } } } */
+/* { dg-skip-if "" { powerpc*-*-darwin* } { "*" } { "" } } */
+/* { dg-require-effective-target powerpc_htm_ok } */
+/* { dg-options "-O2 -mhtm" } */
+
+/* { dg-final { scan-assembler-times "tbegin\\." 1 } } */
+/* { dg-final { scan-assembler-times "tend\\." 2 } } */
+/* { dg-final { scan-assembler-times "tabort\\." 2 } } */
+/* { dg-final { scan-assembler-times "tabortdc\\." 1 } } */
+/* { dg-final { scan-assembler-times "tabortdci\\." 1 } } */
+/* { dg-final { scan-assembler-times "tabortwc\\." 1 } } */
+/* { dg-final { scan-assembler-times "tabortwci\\." 2 } } */
+/* { dg-final { scan-assembler-times "tcheck\\." 1 } } */
+/* { dg-final { scan-assembler-times "trechkpt\\." 1 } } */
+/* { dg-final { scan-assembler-times "treclaim\\." 1 } } */
+/* { dg-final { scan-assembler-times "tsr\\." 3 } } */
+/* { dg-final { scan-assembler-times "mfspr" 4 } } */
+/* { dg-final { scan-assembler-times "mtspr" 4 } } */
+
+void use_builtins (long *p, char code, long *a, long *b)
+{
+ p[0] = __builtin_tbegin (0);
+ p[1] = __builtin_tend (0);
+ p[2] = __builtin_tendall ();
+ p[3] = __builtin_tabort (0);
+ p[4] = __builtin_tabort (code);
+
+ p[5] = __builtin_tabortdc (0xf, a[5], b[5]);
+ p[6] = __builtin_tabortdci (0xf, a[6], 13);
+ p[7] = __builtin_tabortwc (0xf, a[7], b[7]);
+ p[8] = __builtin_tabortwci (0xf, a[8], 13);
+
+ p[9] = __builtin_tcheck (5);
+ p[10] = __builtin_trechkpt ();
+ p[11] = __builtin_treclaim (0);
+ p[12] = __builtin_tresume ();
+ p[13] = __builtin_tsuspend ();
+ p[14] = __builtin_tsr (0);
+ p[15] = __builtin_ttest (); /* This expands to a tabortwci. */
+
+
+ p[16] = __builtin_get_texasr ();
+ p[17] = __builtin_get_texasru ();
+ p[18] = __builtin_get_tfhar ();
+ p[19] = __builtin_get_tfiar ();
+
+ __builtin_set_texasr (a[20]);
+ __builtin_set_texasru (a[21]);
+ __builtin_set_tfhar (a[22]);
+ __builtin_set_tfiar (a[23]);
+}
--- /dev/null
+/* This checks the availability of the XL compiler intrinsics for
+ transactional execution with the expected prototypes. */
+
+/* { dg-do compile { target { powerpc*-*-* } } } */
+/* { dg-skip-if "" { powerpc*-*-darwin* } { "*" } { "" } } */
+/* { dg-require-effective-target powerpc_htm_ok } */
+/* { dg-options "-O2 -mhtm" } */
+
+#include <htmxlintrin.h>
+
+void
+foo (void *TM_buff, long *result, unsigned char *code)
+{
+ *result++ = __TM_simple_begin ();
+ *result++ = __TM_begin (TM_buff);
+ *result++ = __TM_end ();
+ __TM_abort ();
+ __TM_named_abort (*code);
+ __TM_resume ();
+ __TM_suspend ();
+ *result++ = __TM_is_user_abort (TM_buff);
+ *result++ = __TM_is_named_user_abort (TM_buff, code);
+ *result++ = __TM_is_illegal (TM_buff);
+ *result++ = __TM_is_footprint_exceeded (TM_buff);
+ *result++ = __TM_nesting_depth (TM_buff);
+ *result++ = __TM_is_nested_too_deep (TM_buff);
+ *result++ = __TM_is_conflict (TM_buff);
+ *result++ = __TM_is_failure_persistent (TM_buff);
+ *result++ = __TM_failure_address (TM_buff);
+ *result++ = __TM_failure_code (TM_buff);
+}
+
}
}
+# Return 1 if this is a PowerPC target supporting -mhtm
+
+proc check_effective_target_powerpc_htm_ok { } {
+ if { ([istarget powerpc*-*-*]
+ && ![istarget powerpc-*-linux*paired*])
+ || [istarget rs6000-*-*] } {
+ # HTM is not supported on AIX yet.
+ if { [istarget powerpc*-*-aix*] } {
+ return 0
+ }
+ return [check_no_compiler_messages powerpc_htm_ok object {
+ int main (void) {
+ asm volatile ("tbegin. 0");
+ return 0;
+ }
+ } "-mhtm"]
+ } else {
+ return 0
+ }
+}
+
# Return 1 if this is a PowerPC target supporting -mcpu=cell.
proc check_effective_target_powerpc_ppu_ok { } {
+2014-04-04 Bill Schmidt <wschmidt@linux.vnet.ibm.com>
+
+ Power8 HTM Support
+ Backport from mainline
+ * acinclude.m4 (LIBITM_CHECK_AS_HTM): New.
+ * configure: Rebuild.
+ * configure.tgt (target_cpu): Add -mhtm to XCFLAGS.
+ * config/powerpc/target.h: Include sys/auxv.h and htmintrin.h.
+ (USE_HTM_FASTPATH): Define.
+ (_TBEGIN_STARTED, _TBEGIN_INDETERMINATE, _TBEGIN_PERSISTENT)
+ (_HTM_RETRIES) New macros.
+ (htm_abort, htm_abort_should_retry, htm_available, htm_begin, htm_init)
+ (htm_begin_success, htm_commit, htm_transaction_active): New functions.
+
2014-03-26 Jakub Jelinek <jakub@redhat.com>
* config/linux/futex_bits.h: Include errno.h.
;;
esac])
+dnl Check if as supports HTM instructions.
+AC_DEFUN([LIBITM_CHECK_AS_HTM], [
+case "${target_cpu}" in
+powerpc*)
+ AC_CACHE_CHECK([if the assembler supports HTM], libitm_cv_as_htm, [
+ AC_TRY_COMPILE([], [asm("tbegin. 0; tend. 0");],
+ [libitm_cv_as_htm=yes], [libitm_cv_as_htm=no])
+ ])
+ if test x$libitm_cv_as_htm = xyes; then
+ AC_DEFINE(HAVE_AS_HTM, 1, [Define to 1 if the assembler supports HTM.])
+ fi
+ ;;
+esac])
+
sinclude(../libtool.m4)
dnl The lines below arrange for aclocal not to bring an installed
dnl libtool.m4 into aclocal.m4, while still arranging for automake to
see the files COPYING3 and COPYING.RUNTIME respectively. If not, see
<http://www.gnu.org/licenses/>. */
+#ifdef HAVE_SYS_AUXV_H
+#include <sys/auxv.h>
+#endif
+
namespace GTM HIDDEN {
typedef int v128 __attribute__((vector_size(16), may_alias, aligned(16)));
__asm volatile ("" : : : "memory");
}
+// Use HTM if it is supported by the system.
+// See gtm_thread::begin_transaction for how these functions are used.
+#if defined (__linux__) \
+ && defined (HAVE_AS_HTM) \
+ && defined (HAVE_GETAUXVAL) \
+ && defined (AT_HWCAP2) \
+ && defined (PPC_FEATURE2_HAS_HTM)
+
+#include <htmintrin.h>
+
+#define USE_HTM_FASTPATH
+
+#define _TBEGIN_STARTED 0
+#define _TBEGIN_INDETERMINATE 1
+#define _TBEGIN_PERSISTENT 2
+
+/* Number of retries for transient failures. */
+#define _HTM_RETRIES 10
+
+static inline bool
+htm_available (void)
+{
+ return (getauxval (AT_HWCAP2) & PPC_FEATURE2_HAS_HTM) ? true : false;
+}
+
+static inline uint32_t
+htm_init (void)
+{
+ // Maximum number of times we try to execute a transaction
+ // as a HW transaction.
+ return htm_available () ? _HTM_RETRIES : 0;
+}
+
+static inline uint32_t
+htm_begin (void)
+{
+ if (__builtin_expect (__builtin_tbegin (0), 1))
+ return _TBEGIN_STARTED;
+
+ if (_TEXASRU_FAILURE_PERSISTENT (__builtin_get_texasru ()))
+ return _TBEGIN_PERSISTENT;
+
+ return _TBEGIN_INDETERMINATE;
+}
+
+static inline bool
+htm_begin_success (uint32_t begin_ret)
+{
+ return begin_ret == _TBEGIN_STARTED;
+}
+
+static inline void
+htm_commit (void)
+{
+ __builtin_tend (0);
+}
+
+static inline void
+htm_abort (void)
+{
+ __builtin_tabort (0);
+}
+
+static inline bool
+htm_abort_should_retry (uint32_t begin_ret)
+{
+ return begin_ret != _TBEGIN_PERSISTENT;
+}
+
+/* Returns true iff a hardware transaction is currently being executed. */
+static inline bool
+htm_transaction_active (void)
+{
+ return (_HTM_STATE (__builtin_ttest ()) == _HTM_TRANSACTIONAL);
+}
+
+#endif
+
} // namespace GTM
esac
LIBITM_CHECK_AS_HTM
+case "${target_cpu}" in
+powerpc*)
+ { $as_echo "$as_me:${as_lineno-$LINENO}: checking if the assembler supports HTM" >&5
+$as_echo_n "checking if the assembler supports HTM... " >&6; }
+if test "${libitm_cv_as_htm+set}" = set; then :
+ $as_echo_n "(cached) " >&6
+else
+
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+
+int
+main ()
+{
+asm("tbegin. 0; tend. 0");
+ ;
+ return 0;
+}
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"; then :
+ libitm_cv_as_htm=yes
+else
+ libitm_cv_as_htm=no
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $libitm_cv_as_htm" >&5
+$as_echo "$libitm_cv_as_htm" >&6; }
+ if test x$libitm_cv_as_htm = xyes; then
+
+$as_echo "#define HAVE_AS_HTM 1" >>confdefs.h
+
+ fi
+ ;;
+esac
+
{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether weak refs work like ELF" >&5
$as_echo_n "checking whether weak refs work like ELF... " >&6; }
# work out any special compilation flags as necessary.
case "${target_cpu}" in
alpha*) ARCH=alpha ;;
- rs6000 | powerpc*) ARCH=powerpc ;;
+ rs6000 | powerpc*)
+ XCFLAGS="${XCFLAGS} -mhtm"
+ ARCH=powerpc
+ ;;
arm*) ARCH=arm ;;