;; Hardware Transactional Memory (HTM) patterns.
;; Copyright (C) 2013-2015 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_TABORTXC
   UNSPECV_HTM_TABORTXCI
   UNSPECV_HTM_TBEGIN
   UNSPECV_HTM_TCHECK
   UNSPECV_HTM_TEND
   UNSPECV_HTM_TRECHKPT
   UNSPECV_HTM_TRECLAIM
   UNSPECV_HTM_TSR
   UNSPECV_HTM_TTEST
   UNSPECV_HTM_MFSPR
   UNSPECV_HTM_MTSPR
  ])


(define_insn "tabort"
  [(set (match_operand:CC 1 "cc_reg_operand" "=x")
	(unspec_volatile:CC [(match_operand:SI 0 "gpc_reg_operand" "r")]
			    UNSPECV_HTM_TABORT))]
  "TARGET_HTM"
  "tabort. %0"
  [(set_attr "type" "htm")
   (set_attr "length" "4")])

(define_insn "tabort<wd>c"
  [(set (match_operand:CC 3 "cc_reg_operand" "=x")
	(unspec_volatile:CC [(match_operand 0 "u5bit_cint_operand" "n")
			     (match_operand:GPR 1 "gpc_reg_operand" "r")
			     (match_operand:GPR 2 "gpc_reg_operand" "r")]
			    UNSPECV_HTM_TABORTXC))]
  "TARGET_HTM"
  "tabort<wd>c. %0,%1,%2"
  [(set_attr "type" "htm")
   (set_attr "length" "4")])

(define_insn "tabort<wd>ci"
  [(set (match_operand:CC 3 "cc_reg_operand" "=x")
	(unspec_volatile:CC [(match_operand 0 "u5bit_cint_operand" "n")
			     (match_operand:GPR 1 "gpc_reg_operand" "r")
			     (match_operand 2 "s5bit_cint_operand" "n")]
			    UNSPECV_HTM_TABORTXCI))]
  "TARGET_HTM"
  "tabort<wd>ci. %0,%1,%2"
  [(set_attr "type" "htm")
   (set_attr "length" "4")])

(define_insn "tbegin"
  [(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_insn "tcheck"
  [(set (match_operand:CC 0 "cc_reg_operand" "=y")
	(unspec_volatile:CC [(const_int 0)]
			    UNSPECV_HTM_TCHECK))]
  "TARGET_HTM"
  "tcheck %0"
  [(set_attr "type" "htm")
   (set_attr "length" "4")])

(define_insn "tend"
  [(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_insn "trechkpt"
  [(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_insn "treclaim"
  [(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_insn "tsr"
  [(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 "ttest"
  [(set (match_operand:CC 0 "cc_reg_operand" "=x")
	(unspec_volatile:CC [(const_int 0)]
			    UNSPECV_HTM_TTEST))]
  "TARGET_HTM"
  "tabortwci. 0,1,0"
  [(set_attr "type" "htm")
   (set_attr "length" "4")])

(define_insn "htm_mfspr_<mode>"
  [(set (match_operand:GPR 0 "gpc_reg_operand" "=r")
        (unspec_volatile:GPR [(match_operand 1 "u10bit_cint_operand" "n")
			      (match_operand:GPR 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:GPR 2 "htm_spr_reg_operand" "")
        (unspec_volatile:GPR [(match_operand:GPR 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")])
