219 lines
7.0 KiB
Markdown
219 lines
7.0 KiB
Markdown
|
;; GCC machine description for ARC atomic instructions.
|
||
|
;; Copyright (C) 2015-2021 Free Software Foundation, Inc.
|
||
|
;;
|
||
|
;; 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_mode_iterator QHSI [QI HI SI])
|
||
|
(define_code_iterator atomicop [plus minus ior xor and])
|
||
|
(define_code_attr atomic_optab
|
||
|
[(ior "or") (xor "xor") (and "and") (plus "add") (minus "sub")])
|
||
|
|
||
|
(define_expand "memory_barrier"
|
||
|
[(set (match_dup 0)
|
||
|
(unspec:BLK [(match_dup 0)] UNSPEC_ARC_MEMBAR))]
|
||
|
""
|
||
|
{
|
||
|
operands[0] = gen_rtx_MEM (BLKmode, gen_rtx_SCRATCH (Pmode));
|
||
|
MEM_VOLATILE_P (operands[0]) = 1;
|
||
|
})
|
||
|
|
||
|
;; A compiler-only memory barrier for ARC700. Generic code, when
|
||
|
;; checking for the existence of various named patterns, uses
|
||
|
;; asm("":::"memory") when we don't need an actual instruction. For
|
||
|
;; ARCHS, we use a hardware data memory barrier that waits for
|
||
|
;; completion of current data memory operations before initiating
|
||
|
;; similar data memory operations.
|
||
|
(define_insn "*memory_barrier"
|
||
|
[(set (match_operand:BLK 0 "" "")
|
||
|
(unspec:BLK [(match_dup 0)] UNSPEC_ARC_MEMBAR))]
|
||
|
""
|
||
|
{
|
||
|
if (TARGET_HS)
|
||
|
{
|
||
|
return "dmb\\t3";
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
return "";
|
||
|
}
|
||
|
}
|
||
|
[(set_attr "type" "multi")
|
||
|
(set_attr "length" "4")])
|
||
|
|
||
|
(define_expand "atomic_compare_and_swap<mode>"
|
||
|
[(match_operand:SI 0 "register_operand" "") ;; bool out
|
||
|
(match_operand:QHSI 1 "register_operand" "") ;; val out
|
||
|
(match_operand:QHSI 2 "mem_noofs_operand" "");; memory
|
||
|
(match_operand:QHSI 3 "register_operand" "") ;; expected
|
||
|
(match_operand:QHSI 4 "register_operand" "") ;; desired
|
||
|
(match_operand:SI 5 "const_int_operand") ;; is_weak
|
||
|
(match_operand:SI 6 "const_int_operand") ;; mod_s
|
||
|
(match_operand:SI 7 "const_int_operand")] ;; mod_f
|
||
|
"TARGET_ATOMIC"
|
||
|
{
|
||
|
arc_expand_compare_and_swap (operands);
|
||
|
DONE;
|
||
|
})
|
||
|
|
||
|
(define_insn_and_split "atomic_compare_and_swapsi_1"
|
||
|
[(set (reg:CC_Z CC_REG) ;; bool out
|
||
|
(unspec_volatile:CC_Z [(const_int 0)] VUNSPEC_ARC_CAS))
|
||
|
(set (match_operand:SI 0 "register_operand" "=&r") ;; val out
|
||
|
(match_operand:SI 1 "mem_noofs_operand" "+ATO")) ;; memory
|
||
|
(set (match_dup 1)
|
||
|
(unspec_volatile:SI
|
||
|
[(match_operand:SI 2 "register_operand" "r") ;; expect
|
||
|
(match_operand:SI 3 "register_operand" "r") ;; desired
|
||
|
(match_operand:SI 4 "const_int_operand") ;; is_weak
|
||
|
(match_operand:SI 5 "const_int_operand") ;; mod_s
|
||
|
(match_operand:SI 6 "const_int_operand")] ;; mod_f
|
||
|
VUNSPEC_ARC_CAS))]
|
||
|
"TARGET_ATOMIC"
|
||
|
"#"
|
||
|
"&& reload_completed"
|
||
|
[(const_int 0)]
|
||
|
{
|
||
|
arc_split_compare_and_swap (operands);
|
||
|
DONE;
|
||
|
})
|
||
|
|
||
|
(define_insn "arc_load_exclusivesi"
|
||
|
[(set (match_operand:SI 0 "register_operand" "=r")
|
||
|
(unspec_volatile:SI
|
||
|
[(match_operand:SI 1 "mem_noofs_operand" "ATO")]
|
||
|
VUNSPEC_ARC_LL))]
|
||
|
"TARGET_ATOMIC"
|
||
|
"llock %0,%1"
|
||
|
[(set_attr "type" "load")
|
||
|
(set_attr "iscompact" "false")
|
||
|
(set_attr "predicable" "no")
|
||
|
(set_attr "length" "*")])
|
||
|
|
||
|
(define_insn "arc_store_exclusivesi"
|
||
|
[(set (match_operand:SI 0 "mem_noofs_operand" "=ATO")
|
||
|
(unspec_volatile:SI[(match_operand:SI 1 "register_operand" "r")]
|
||
|
VUNSPEC_ARC_SC))
|
||
|
(clobber (reg:CC_Z CC_REG))]
|
||
|
"TARGET_ATOMIC"
|
||
|
"scond %1,%0"
|
||
|
[(set_attr "type" "store")
|
||
|
(set_attr "iscompact" "false")
|
||
|
(set_attr "predicable" "no")
|
||
|
(set_attr "length" "*")])
|
||
|
|
||
|
(define_expand "atomic_exchangesi"
|
||
|
[(match_operand:SI 0 "register_operand" "")
|
||
|
(match_operand:SI 1 "mem_noofs_operand" "")
|
||
|
(match_operand:SI 2 "register_operand" "")
|
||
|
(match_operand:SI 3 "const_int_operand" "")]
|
||
|
"TARGET_ARC700 || TARGET_V2"
|
||
|
{
|
||
|
enum memmodel model = (enum memmodel) INTVAL (operands[3]);
|
||
|
|
||
|
if (model == MEMMODEL_SEQ_CST)
|
||
|
emit_insn (gen_sync (const1_rtx));
|
||
|
emit_insn (gen_exchangesi (operands[0], operands[1], operands[2]));
|
||
|
DONE;
|
||
|
})
|
||
|
|
||
|
(define_insn "exchangesi"
|
||
|
[(set (match_operand:SI 0 "register_operand" "=r")
|
||
|
(unspec_volatile:SI [(match_operand:SI 1 "mem_noofs_operand" "+ATO")]
|
||
|
VUNSPEC_ARC_EX))
|
||
|
(set (match_dup 1)
|
||
|
(match_operand:SI 2 "register_operand" "0"))]
|
||
|
""
|
||
|
"ex %0,%1"
|
||
|
[(set_attr "type" "load")
|
||
|
(set_attr "iscompact" "false")
|
||
|
(set_attr "predicable" "no")
|
||
|
(set_attr "length" "*")])
|
||
|
|
||
|
(define_expand "atomic_<atomic_optab>si"
|
||
|
[(match_operand:SI 0 "mem_noofs_operand" "") ;; memory
|
||
|
(atomicop:SI (match_dup 0)
|
||
|
(match_operand:SI 1 "register_operand" "")) ;; operand
|
||
|
(match_operand:SI 2 "const_int_operand" "")] ;; model
|
||
|
"TARGET_ATOMIC"
|
||
|
{
|
||
|
arc_expand_atomic_op (<CODE>, operands[0], operands[1],
|
||
|
NULL_RTX, NULL_RTX, operands[2]);
|
||
|
DONE;
|
||
|
})
|
||
|
|
||
|
(define_expand "atomic_nandsi"
|
||
|
[(match_operand:SI 0 "mem_noofs_operand" "") ;; memory
|
||
|
(match_operand:SI 1 "register_operand" "") ;; operand
|
||
|
(match_operand:SI 2 "const_int_operand" "")] ;; model
|
||
|
"TARGET_ATOMIC"
|
||
|
{
|
||
|
arc_expand_atomic_op (NOT, operands[0], operands[1],
|
||
|
NULL_RTX, NULL_RTX, operands[2]);
|
||
|
DONE;
|
||
|
})
|
||
|
|
||
|
(define_expand "atomic_fetch_<atomic_optab>si"
|
||
|
[(match_operand:SI 0 "register_operand" "") ;; output
|
||
|
(match_operand:SI 1 "mem_noofs_operand" "") ;; memory
|
||
|
(atomicop:SI (match_dup 1)
|
||
|
(match_operand:SI 2 "register_operand" "")) ;; operand
|
||
|
(match_operand:SI 3 "const_int_operand" "")] ;; model
|
||
|
"TARGET_ATOMIC"
|
||
|
{
|
||
|
arc_expand_atomic_op (<CODE>, operands[1], operands[2],
|
||
|
operands[0], NULL_RTX, operands[3]);
|
||
|
DONE;
|
||
|
})
|
||
|
|
||
|
(define_expand "atomic_fetch_nandsi"
|
||
|
[(match_operand:SI 0 "register_operand" "") ;; output
|
||
|
(match_operand:SI 1 "mem_noofs_operand" "") ;; memory
|
||
|
(match_operand:SI 2 "register_operand" "") ;; operand
|
||
|
(match_operand:SI 3 "const_int_operand" "")] ;; model
|
||
|
"TARGET_ATOMIC"
|
||
|
{
|
||
|
arc_expand_atomic_op (NOT, operands[1], operands[2],
|
||
|
operands[0], NULL_RTX, operands[3]);
|
||
|
DONE;
|
||
|
})
|
||
|
|
||
|
(define_expand "atomic_<atomic_optab>_fetchsi"
|
||
|
[(match_operand:SI 0 "register_operand" "") ;; output
|
||
|
(match_operand:SI 1 "mem_noofs_operand" "") ;; memory
|
||
|
(atomicop:SI (match_dup 1)
|
||
|
(match_operand:SI 2 "register_operand" "")) ;; operand
|
||
|
(match_operand:SI 3 "const_int_operand" "")] ;; model
|
||
|
"TARGET_ATOMIC"
|
||
|
{
|
||
|
arc_expand_atomic_op (<CODE>, operands[1], operands[2],
|
||
|
NULL_RTX, operands[0], operands[3]);
|
||
|
DONE;
|
||
|
})
|
||
|
|
||
|
(define_expand "atomic_nand_fetchsi"
|
||
|
[(match_operand:SI 0 "register_operand" "") ;; output
|
||
|
(match_operand:SI 1 "mem_noofs_operand" "") ;; memory
|
||
|
(match_operand:SI 2 "register_operand" "") ;; operand
|
||
|
(match_operand:SI 3 "const_int_operand" "")] ;; model
|
||
|
"TARGET_ATOMIC"
|
||
|
{
|
||
|
arc_expand_atomic_op (NOT, operands[1], operands[2],
|
||
|
NULL_RTX, operands[0], operands[3]);
|
||
|
DONE;
|
||
|
})
|
||
|
|