// Copyright (c) 2020, 2025, Oracle and/or its affiliates. All rights reserved.
// Copyright (c) 2016, 2021, Red Hat Inc. All rights reserved.
// DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
//
// This code is free software; you can redistribute it and/or modify it
// under the terms of the GNU General Public License version 2 only, as
// published by the Free Software Foundation.
//
// This code 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
// version 2 for more details (a copy is included in the LICENSE file that
// accompanied this code).
//
// You should have received a copy of the GNU General Public License version
// 2 along with this work; if not, write to the Free Software Foundation,
// Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
//
// Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
// or visit www.oracle.com if you need additional information or have any
// questions.
//
//

// BEGIN This file is automatically generated. Do not edit --------------

// Sundry CAS operations.  Note that release is always true,
// regardless of the memory ordering of the CAS.  This is because we
// need the volatile case to be sequentially consistent but there is
// no trailing StoreLoad barrier emitted by C2.  Unfortunately we
// can't check the type of memory ordering here, so we always emit a
// STLXR.

// This section is generated from aarch64_atomic_ad.m4

dnl Return Arg1 with two spaces before it. We need this because m4
dnl strips leading spaces from macro args.
define(`INDENT', `  $1')dnl
dnl
dnl
dnl
dnl ====================== CompareAndExchange*
dnl
define(`CAE_INSN1',
`
instruct compareAndExchange$1$7(iReg$2NoSp res, indirect mem, iReg$2 oldval, iReg$2 newval, rFlagsReg cr) %{
ifelse($7,Acq,INDENT(predicate(needs_acquiring_load_exclusive(n));),`dnl')
  match(Set res (CompareAndExchange$1 mem (Binary oldval newval)));
  ins_cost(`'ifelse($7,Acq,,2*)VOLATILE_REF_COST);
  effect(TEMP_DEF res, KILL cr);
  format %{
    "cmpxchg$5`'ifelse($7,Acq,_acq,) $res = $mem, $oldval, $newval\t# ($3) if $mem == $oldval then $mem <-- $newval"
  %}
  ins_encode %{
    __ cmpxchg($mem$$Register, $oldval$$Register, $newval$$Register,
               Assembler::$4, /*acquire*/ ifelse($7,Acq,true,false), /*release*/ true,
               /*weak*/ false, $res$$Register);
    __ $6($res$$Register, $res$$Register);
  %}
  ins_pipe(pipe_slow);
%}')dnl
define(`CAE_INSN2',
`
instruct compareAndExchange$1$6(iReg$2NoSp res, indirect mem, iReg$2 oldval, iReg$2 newval, rFlagsReg cr) %{
ifelse($1$6,PAcq,INDENT(predicate(needs_acquiring_load_exclusive(n) && (n->as_LoadStore()->barrier_data() == 0));),
       $1$6,NAcq,INDENT(predicate(needs_acquiring_load_exclusive(n) && n->as_LoadStore()->barrier_data() == 0);),
       $1,P,INDENT(predicate(n->as_LoadStore()->barrier_data() == 0);),
       $1,N,INDENT(predicate(n->as_LoadStore()->barrier_data() == 0);),
       $6,Acq,INDENT(predicate(needs_acquiring_load_exclusive(n));),
       `dnl')
  match(Set res (CompareAndExchange$1 mem (Binary oldval newval)));
  ins_cost(`'ifelse($6,Acq,,2*)VOLATILE_REF_COST);
  effect(TEMP_DEF res, KILL cr);
  format %{
    "cmpxchg$5`'ifelse($6,Acq,_acq,) $res = $mem, $oldval, $newval\t# ($3) if $mem == $oldval then $mem <-- $newval"
  %}
  ins_encode %{
    __ cmpxchg($mem$$Register, $oldval$$Register, $newval$$Register,
               Assembler::$4, /*acquire*/ ifelse($6,Acq,true,false), /*release*/ true,
               /*weak*/ false, $res$$Register);
  %}
  ins_pipe(pipe_slow);
%}')dnl
dnl
CAE_INSN1(B,    I,  byte,       byte,       b,  sxtbw,  )
CAE_INSN1(S,    I,  short,      halfword,   s,  sxthw,  )
CAE_INSN2(I,    I,  int,        word,       w,  ,   )
CAE_INSN2(L,    L,  long,       xword,      ,   ,   )
CAE_INSN2(N,    N,  narrow oop, word,       w,  ,   )
CAE_INSN2(P,    P,  ptr,        xword,      ,   ,   )
dnl
CAE_INSN1(B,    I,  byte,       byte,       b,  sxtbw,  Acq)
CAE_INSN1(S,    I,  short,      halfword,   s,  sxthw,  Acq)
CAE_INSN2(I,    I,  int,        word,       w,  Acq)
CAE_INSN2(L,    L,  long,       xword,      ,   Acq)
CAE_INSN2(N,    N,  narrow oop, word,       w,  Acq)
CAE_INSN2(P,    P,  ptr,        xword,      ,   Acq)
dnl
dnl
dnl
dnl ====================== (Weak)CompareAndSwap*
dnl
define(`CAS_INSN1',
`
instruct ifelse($7,Weak,'weakCompare`,'compare`)AndSwap$1$6(iRegINoSp res, indirect mem, iReg$2 oldval, iReg$2 newval, rFlagsReg cr) %{
ifelse($6,Acq,INDENT(predicate(needs_acquiring_load_exclusive(n));),`dnl')
  match(Set res ($7CompareAndSwap$1 mem (Binary oldval newval)));
  ins_cost(`'ifelse($6,Acq,,2*)VOLATILE_REF_COST);
  effect(KILL cr);
  format %{
    "cmpxchg$5`'ifelse($6,Acq,_acq,)`'ifelse($7,Weak,_weak) $res = $mem, $oldval, $newval\t# ($3) if $mem == $oldval then $mem <-- $newval"
    "csetw $res, EQ\t# $res <-- (EQ ? 1 : 0)"
  %}
  ins_encode %{
    __ cmpxchg($mem$$Register, $oldval$$Register, $newval$$Register,
               Assembler::$4, /*acquire*/ ifelse($6,Acq,true,false), /*release*/ true,
               /*weak*/ ifelse($7,Weak,true,false), noreg);
    __ csetw($res$$Register, Assembler::EQ);
  %}
  ins_pipe(pipe_slow);
%}')dnl
dnl
define(`CAS_INSN2',
`
instruct ifelse($7,Weak,'weakCompare`,'compare`)AndSwap$1$6(iRegINoSp res, indirect mem, iReg$2 oldval, iReg$2 newval, rFlagsReg cr) %{
ifelse($1$6,PAcq,INDENT(predicate(needs_acquiring_load_exclusive(n) && (n->as_LoadStore()->barrier_data() == 0));),
       $1$6,NAcq,INDENT(predicate(needs_acquiring_load_exclusive(n) && n->as_LoadStore()->barrier_data() == 0);),
       $1,P,INDENT(predicate(n->as_LoadStore()->barrier_data() == 0);),
       $1,N,INDENT(predicate(n->as_LoadStore()->barrier_data() == 0);),
       $6,Acq,INDENT(predicate(needs_acquiring_load_exclusive(n));),
       `dnl')
  match(Set res ($7CompareAndSwap$1 mem (Binary oldval newval)));
  ins_cost(`'ifelse($6,Acq,,2*)VOLATILE_REF_COST);
  effect(KILL cr);
  format %{
    "cmpxchg$5`'ifelse($6,Acq,_acq,)`'ifelse($7,Weak,_weak) $res = $mem, $oldval, $newval\t# ($3) if $mem == $oldval then $mem <-- $newval"
    "csetw $res, EQ\t# $res <-- (EQ ? 1 : 0)"
  %}
  ins_encode %{
    __ cmpxchg($mem$$Register, $oldval$$Register, $newval$$Register,
               Assembler::$4, /*acquire*/ ifelse($6,Acq,true,false), /*release*/ true,
               /*weak*/ ifelse($7,Weak,true,false), noreg);
    __ csetw($res$$Register, Assembler::EQ);
  %}
  ins_pipe(pipe_slow);
%}')dnl
dnl
CAS_INSN1(B,    I,  byte,       byte,       b,  ,           )
CAS_INSN1(S,    I,  short,      halfword,   s,  ,           )
CAS_INSN2(I,    I,  int,        word,       w,  ,           )
CAS_INSN2(L,    L,  long,       xword,      ,   ,           )
CAS_INSN2(N,    N,  narrow oop, word,       w,  ,           )
CAS_INSN2(P,    P,  ptr,        xword,      ,   ,           )
dnl
CAS_INSN1(B,    I,  byte,       byte,       b,  Acq,        )
CAS_INSN1(S,    I,  short,      halfword,   s,  Acq,        )
CAS_INSN2(I,    I,  int,        word,       w,  Acq,        )
CAS_INSN2(L,    L,  long,       xword,      ,   Acq,        )
CAS_INSN2(N,    N,  narrow oop, word,       w,  Acq,        )
CAS_INSN2(P,    P,  ptr,        xword,      ,   Acq,        )
dnl
CAS_INSN1(B,    I,  byte,       byte,       b,  ,       Weak)
CAS_INSN1(S,    I,  short,      halfword,   s,  ,       Weak)
CAS_INSN2(I,    I,  int,        word,       w,  ,       Weak)
CAS_INSN2(L,    L,  long,       xword,      ,   ,       Weak)
CAS_INSN2(N,    N,  narrow oop, word,       w,  ,       Weak)
CAS_INSN2(P,    P,  ptr,        xword,      ,   ,       Weak)
dnl
CAS_INSN1(B,    I,  byte,       byte,       b,  Acq,    Weak)
CAS_INSN1(S,    I,  short,      halfword,   s,  Acq,    Weak)
CAS_INSN2(I,    I,  int,        word,       w,  Acq,    Weak)
CAS_INSN2(L,    L,  long,       xword,      ,   Acq,    Weak)
CAS_INSN2(N,    N,  narrow oop, word,       w,  Acq,    Weak)
CAS_INSN2(P,    P,  ptr,        xword,      ,   Acq,    Weak)
dnl
dnl
dnl
dnl ====================== GetAndSet*
dnl
define(`GAS_INSN1',
`
instruct getAndSet$1$3(indirect mem, iReg$1 newval, iReg$1NoSp oldval) %{
ifelse($1$3,PAcq,INDENT(predicate(needs_acquiring_load_exclusive(n) && (n->as_LoadStore()->barrier_data() == 0));),
       $1$3,NAcq,INDENT(predicate(needs_acquiring_load_exclusive(n) && n->as_LoadStore()->barrier_data() == 0);),
       $1,P,INDENT(predicate(n->as_LoadStore()->barrier_data() == 0);),
       $1,N,INDENT(predicate(n->as_LoadStore()->barrier_data() == 0);),
       $3,Acq,INDENT(predicate(needs_acquiring_load_exclusive(n));),
       `dnl')
  match(Set oldval (GetAndSet$1 mem newval));
  ins_cost(`'ifelse($3,Acq,,2*)VOLATILE_REF_COST);
  format %{ "atomic_xchg$2`'ifelse($3,Acq,_acq)  $oldval, $newval, [$mem]" %}
  ins_encode %{
    __ atomic_xchg`'ifelse($3,Acq,al)$2($oldval$$Register, $newval$$Register, as_Register($mem$$base));
  %}
  ins_pipe(pipe_serial);
%}')dnl
dnl
GAS_INSN1(I,    w,  )
GAS_INSN1(L,    ,   )
GAS_INSN1(N,    w,  )
GAS_INSN1(P,    ,   )
dnl
GAS_INSN1(I,    w,  Acq)
GAS_INSN1(L,    ,   Acq)
GAS_INSN1(N,    w,  Acq)
GAS_INSN1(P,    ,   Acq)
dnl
dnl
dnl
dnl ====================== GetAndAdd*
dnl
define(`GAA_INSN1',
`
instruct getAndAdd$1$4$5$6(indirect mem, `'ifelse($5,NoRes,Universe dummy,iReg$1NoSp newval), `'ifelse($6,Const,imm$1AddSub incr,iReg$2 incr)) %{
ifelse($4$5,AcqNoRes,INDENT(predicate(n->as_LoadStore()->result_not_used() && needs_acquiring_load_exclusive(n));),
       $5,NoRes,INDENT(predicate(n->as_LoadStore()->result_not_used());),
       $4,Acq,INDENT(predicate(needs_acquiring_load_exclusive(n));),
       `dnl')
  match(Set ifelse($5,NoRes,dummy,newval) (GetAndAdd$1 mem incr));
  ins_cost(`'ifelse($4,Acq,,2*)VOLATILE_REF_COST`'ifelse($5,NoRes,,+1));
  format %{ "get_and_add$1`'ifelse($4,Acq,_acq) `'ifelse($5,NoRes,noreg,$newval), [$mem], $incr" %}
  ins_encode %{
    __ atomic_add`'ifelse($4,Acq,al)$3(`'ifelse($5,NoRes,noreg,$newval$$Register), `'ifelse($6,Const,$incr$$constant,$incr$$Register), as_Register($mem$$base));
  %}
  ins_pipe(pipe_serial);
%}')dnl
dnl
dnl
GAA_INSN1(I,    IorL2I,     w,  ,       ,           )
GAA_INSN1(I,    IorL2I,     w,  Acq,    ,           )
GAA_INSN1(I,    IorL2I,     w,  ,       NoRes,      )
GAA_INSN1(I,    IorL2I,     w,  Acq,    NoRes,      )
GAA_INSN1(I,    I,          w,  ,       ,       Const)
GAA_INSN1(I,    I,          w,  Acq,    ,       Const)
GAA_INSN1(I,    I,          w,  ,       NoRes,  Const)
GAA_INSN1(I,    I,          w,  Acq,    NoRes,  Const)
dnl
GAA_INSN1(L,    L,          ,   ,       ,           )
GAA_INSN1(L,    L,          ,   Acq,    ,           )
GAA_INSN1(L,    L,          ,   ,       NoRes,      )
GAA_INSN1(L,    L,          ,   Acq,    NoRes,      )
GAA_INSN1(L,    L,          ,   ,       ,       Const)
GAA_INSN1(L,    L,          ,   Acq,    ,       Const)
GAA_INSN1(L,    L,          ,   ,       NoRes,  Const)
GAA_INSN1(L,    L,          ,   Acq,    NoRes,  Const)
dnl
