xref: /freebsd/contrib/llvm-project/llvm/lib/Target/RISCV/RISCVInstrInfoZa.td (revision b64c5a0ace59af62eff52bfe110a521dc73c937b)
1//===-- RISCVInstrInfoZa.td - RISC-V Atomic instructions ---*- tablegen -*-===//
2//
3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4// See https://llvm.org/LICENSE.txt for license information.
5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6//
7//===----------------------------------------------------------------------===//
8//
9// This file describes the RISC-V instructions from the standard atomic 'Za*'
10// extensions:
11//   - Zawrs (v1.0) : Wait-on-Reservation-Set.
12//   - Zacas (v1.0-rc1) : Atomic Compare-and-Swap.
13//   - Zabha (v1.0-rc1) : Byte and Halfword Atomic Memory Operations.
14//
15//===----------------------------------------------------------------------===//
16
17//===----------------------------------------------------------------------===//
18// Zacas (Atomic Compare-and-Swap)
19//===----------------------------------------------------------------------===//
20
21def GPRPairRV32Operand : AsmOperandClass {
22  let Name = "GPRPairRV32";
23  let ParserMethod = "parseGPRPair<false>";
24  let PredicateMethod = "isGPRPair";
25  let RenderMethod = "addRegOperands";
26}
27
28def GPRPairRV64Operand : AsmOperandClass {
29  let Name = "GPRPairRV64";
30  let ParserMethod = "parseGPRPair<true>";
31  let PredicateMethod = "isGPRPair";
32  let RenderMethod = "addRegOperands";
33}
34
35def GPRPairRV32 : RegisterOperand<GPRPair> {
36  let ParserMatchClass = GPRPairRV32Operand;
37}
38
39def GPRPairRV64 : RegisterOperand<GPRPair> {
40  let ParserMatchClass = GPRPairRV64Operand;
41}
42
43let hasSideEffects = 0, mayLoad = 1, mayStore = 1, Constraints = "$rd = $rd_wb" in
44class AMO_cas<bits<5> funct5, bit aq, bit rl, bits<3> funct3, string opcodestr,
45              DAGOperand RC>
46    : RVInstRAtomic<funct5, aq, rl, funct3, OPC_AMO,
47                    (outs RC:$rd_wb), (ins RC:$rd, GPRMemZeroOffset:$rs1, RC:$rs2),
48                    opcodestr, "$rd, $rs2, $rs1">;
49
50multiclass AMO_cas_aq_rl<bits<5> funct5, bits<3> funct3, string opcodestr,
51                         DAGOperand RC> {
52  def ""     : AMO_cas<funct5, 0, 0, funct3, opcodestr, RC>;
53  def _AQ    : AMO_cas<funct5, 1, 0, funct3, opcodestr # ".aq", RC>;
54  def _RL    : AMO_cas<funct5, 0, 1, funct3, opcodestr # ".rl", RC>;
55  def _AQ_RL : AMO_cas<funct5, 1, 1, funct3, opcodestr # ".aqrl", RC>;
56}
57
58let Predicates = [HasStdExtZacas], IsSignExtendingOpW = 1 in {
59defm AMOCAS_W : AMO_cas_aq_rl<0b00101, 0b010, "amocas.w", GPR>;
60} // Predicates = [HasStdExtZacas]
61
62let Predicates = [HasStdExtZacas, IsRV32], DecoderNamespace = "RV32Zacas"  in {
63defm AMOCAS_D_RV32 : AMO_cas_aq_rl<0b00101, 0b011, "amocas.d", GPRPairRV32>;
64} // Predicates = [HasStdExtZacas, IsRV32]
65
66let Predicates = [HasStdExtZacas, IsRV64] in {
67defm AMOCAS_D_RV64 : AMO_cas_aq_rl<0b00101, 0b011, "amocas.d", GPR>;
68defm AMOCAS_Q : AMO_cas_aq_rl<0b00101, 0b100, "amocas.q", GPRPairRV64>;
69} // Predicates = [HasStdExtZacas, IsRV64]
70
71multiclass AMOCASPat<string AtomicOp, string BaseInst, ValueType vt = XLenVT,
72                     list<Predicate> ExtraPreds = []> {
73  let Predicates = !listconcat([HasStdExtZacas, NotHasStdExtZtso], ExtraPreds) in {
74    def : Pat<(!cast<PatFrag>(AtomicOp#"_monotonic") (vt GPR:$addr),
75                                                     (vt GPR:$cmp),
76                                                     (vt GPR:$new)),
77              (!cast<RVInst>(BaseInst) GPR:$cmp, GPR:$addr, GPR:$new)>;
78    def : Pat<(!cast<PatFrag>(AtomicOp#"_acquire") (vt GPR:$addr),
79                                                   (vt GPR:$cmp),
80                                                   (vt GPR:$new)),
81              (!cast<RVInst>(BaseInst#"_AQ") GPR:$cmp, GPR:$addr, GPR:$new)>;
82    def : Pat<(!cast<PatFrag>(AtomicOp#"_release") (vt GPR:$addr),
83                                                   (vt GPR:$cmp),
84                                                   (vt GPR:$new)),
85              (!cast<RVInst>(BaseInst#"_RL") GPR:$cmp, GPR:$addr, GPR:$new)>;
86    def : Pat<(!cast<PatFrag>(AtomicOp#"_acq_rel") (vt GPR:$addr),
87                                                   (vt GPR:$cmp),
88                                                   (vt GPR:$new)),
89              (!cast<RVInst>(BaseInst#"_AQ_RL") GPR:$cmp, GPR:$addr, GPR:$new)>;
90    def : Pat<(!cast<PatFrag>(AtomicOp#"_seq_cst") (vt GPR:$addr),
91                                                   (vt GPR:$cmp),
92                                                   (vt GPR:$new)),
93              (!cast<RVInst>(BaseInst#"_AQ_RL") GPR:$cmp, GPR:$addr, GPR:$new)>;
94  } // Predicates = !listconcat([HasStdExtZacas, NotHasStdExtZtso], ExtraPreds)
95  let Predicates = !listconcat([HasStdExtZacas, HasStdExtZtso], ExtraPreds) in {
96    def : Pat<(!cast<PatFrag>(AtomicOp#"_monotonic") (vt GPR:$addr),
97                                                     (vt GPR:$cmp),
98                                                     (vt GPR:$new)),
99              (!cast<RVInst>(BaseInst) GPR:$cmp, GPR:$addr, GPR:$new)>;
100    def : Pat<(!cast<PatFrag>(AtomicOp#"_acquire") (vt GPR:$addr),
101                                                   (vt GPR:$cmp),
102                                                   (vt GPR:$new)),
103              (!cast<RVInst>(BaseInst) GPR:$cmp, GPR:$addr, GPR:$new)>;
104    def : Pat<(!cast<PatFrag>(AtomicOp#"_release") (vt GPR:$addr),
105                                                   (vt GPR:$cmp),
106                                                   (vt GPR:$new)),
107              (!cast<RVInst>(BaseInst) GPR:$cmp, GPR:$addr, GPR:$new)>;
108    def : Pat<(!cast<PatFrag>(AtomicOp#"_acq_rel") (vt GPR:$addr),
109                                                   (vt GPR:$cmp),
110                                                   (vt GPR:$new)),
111              (!cast<RVInst>(BaseInst) GPR:$cmp, GPR:$addr, GPR:$new)>;
112    def : Pat<(!cast<PatFrag>(AtomicOp#"_seq_cst") (vt GPR:$addr),
113                                                   (vt GPR:$cmp),
114                                                   (vt GPR:$new)),
115              (!cast<RVInst>(BaseInst) GPR:$cmp, GPR:$addr, GPR:$new)>;
116  } // Predicates = !listconcat([HasStdExtZacas, HasStdExtZtso], ExtraPreds)
117}
118
119defm : AMOCASPat<"atomic_cmp_swap_i32", "AMOCAS_W">;
120defm : AMOCASPat<"atomic_cmp_swap_i64", "AMOCAS_D_RV64", i64, [IsRV64]>;
121
122//===----------------------------------------------------------------------===//
123// Zawrs (Wait-on-Reservation-Set)
124//===----------------------------------------------------------------------===//
125
126let hasSideEffects = 1, mayLoad = 0, mayStore = 0 in
127class WRSInst<bits<12> funct12, string opcodestr>
128    : RVInstI<0b000, OPC_SYSTEM, (outs), (ins), opcodestr, ""> {
129  let rs1 = 0;
130  let rd = 0;
131  let imm12 = funct12;
132}
133
134let Predicates = [HasStdExtZawrs] in {
135def WRS_NTO : WRSInst<0b000000001101, "wrs.nto">, Sched<[]>;
136def WRS_STO : WRSInst<0b000000011101, "wrs.sto">, Sched<[]>;
137} // Predicates = [HasStdExtZawrs]
138
139//===----------------------------------------------------------------------===//
140// Zabha (Byte and Halfword Atomic Memory Operations)
141//===----------------------------------------------------------------------===//
142
143let Predicates = [HasStdExtZabha] in {
144defm AMOSWAP_B  : AMO_rr_aq_rl<0b00001, 0b000, "amoswap.b">,
145                  Sched<[WriteAtomicB, ReadAtomicBA, ReadAtomicBD]>;
146defm AMOADD_B   : AMO_rr_aq_rl<0b00000, 0b000, "amoadd.b">,
147                  Sched<[WriteAtomicB, ReadAtomicBA, ReadAtomicBD]>;
148defm AMOXOR_B   : AMO_rr_aq_rl<0b00100, 0b000, "amoxor.b">,
149                  Sched<[WriteAtomicB, ReadAtomicBA, ReadAtomicBD]>;
150defm AMOAND_B   : AMO_rr_aq_rl<0b01100, 0b000, "amoand.b">,
151                  Sched<[WriteAtomicB, ReadAtomicBA, ReadAtomicBD]>;
152defm AMOOR_B    : AMO_rr_aq_rl<0b01000, 0b000, "amoor.b">,
153                  Sched<[WriteAtomicB, ReadAtomicBA, ReadAtomicBD]>;
154defm AMOMIN_B   : AMO_rr_aq_rl<0b10000, 0b000, "amomin.b">,
155                  Sched<[WriteAtomicB, ReadAtomicBA, ReadAtomicBD]>;
156defm AMOMAX_B   : AMO_rr_aq_rl<0b10100, 0b000, "amomax.b">,
157                  Sched<[WriteAtomicB, ReadAtomicBA, ReadAtomicBD]>;
158defm AMOMINU_B  : AMO_rr_aq_rl<0b11000, 0b000, "amominu.b">,
159                  Sched<[WriteAtomicB, ReadAtomicBA, ReadAtomicBD]>;
160defm AMOMAXU_B  : AMO_rr_aq_rl<0b11100, 0b000, "amomaxu.b">,
161                  Sched<[WriteAtomicB, ReadAtomicBA, ReadAtomicBD]>;
162
163defm AMOSWAP_H  : AMO_rr_aq_rl<0b00001, 0b001, "amoswap.h">,
164                  Sched<[WriteAtomicH, ReadAtomicHA, ReadAtomicHD]>;
165defm AMOADD_H   : AMO_rr_aq_rl<0b00000, 0b001, "amoadd.h">,
166                  Sched<[WriteAtomicH, ReadAtomicHA, ReadAtomicHD]>;
167defm AMOXOR_H   : AMO_rr_aq_rl<0b00100, 0b001, "amoxor.h">,
168                  Sched<[WriteAtomicH, ReadAtomicHA, ReadAtomicHD]>;
169defm AMOAND_H   : AMO_rr_aq_rl<0b01100, 0b001, "amoand.h">,
170                  Sched<[WriteAtomicH, ReadAtomicHA, ReadAtomicHD]>;
171defm AMOOR_H    : AMO_rr_aq_rl<0b01000, 0b001, "amoor.h">,
172                  Sched<[WriteAtomicH, ReadAtomicHA, ReadAtomicHD]>;
173defm AMOMIN_H   : AMO_rr_aq_rl<0b10000, 0b001, "amomin.h">,
174                  Sched<[WriteAtomicH, ReadAtomicHA, ReadAtomicHD]>;
175defm AMOMAX_H   : AMO_rr_aq_rl<0b10100, 0b001, "amomax.h">,
176                  Sched<[WriteAtomicH, ReadAtomicHA, ReadAtomicHD]>;
177defm AMOMINU_H  : AMO_rr_aq_rl<0b11000, 0b001, "amominu.h">,
178                  Sched<[WriteAtomicH, ReadAtomicHA, ReadAtomicHD]>;
179defm AMOMAXU_H  : AMO_rr_aq_rl<0b11100, 0b001, "amomaxu.h">,
180                  Sched<[WriteAtomicH, ReadAtomicHA, ReadAtomicHD]>;
181}
182
183// If Zacas extension is also implemented, Zabha further provides AMOCAS.[B|H].
184let Predicates = [HasStdExtZabha, HasStdExtZacas] in {
185defm AMOCAS_B : AMO_cas_aq_rl<0b00101, 0b000, "amocas.b", GPR>;
186defm AMOCAS_H : AMO_cas_aq_rl<0b00101, 0b001, "amocas.h", GPR>;
187}
188
189/// AMOs
190
191defm : AMOPat<"atomic_swap_i8", "AMOSWAP_B", XLenVT, [HasStdExtZabha]>;
192defm : AMOPat<"atomic_load_add_i8", "AMOADD_B", XLenVT, [HasStdExtZabha]>;
193defm : AMOPat<"atomic_load_and_i8", "AMOAND_B", XLenVT, [HasStdExtZabha]>;
194defm : AMOPat<"atomic_load_or_i8", "AMOOR_B", XLenVT, [HasStdExtZabha]>;
195defm : AMOPat<"atomic_load_xor_i8", "AMOXOR_B", XLenVT, [HasStdExtZabha]>;
196defm : AMOPat<"atomic_load_max_i8", "AMOMAX_B", XLenVT, [HasStdExtZabha]>;
197defm : AMOPat<"atomic_load_min_i8", "AMOMIN_B", XLenVT, [HasStdExtZabha]>;
198defm : AMOPat<"atomic_load_umax_i8", "AMOMAXU_B", XLenVT, [HasStdExtZabha]>;
199defm : AMOPat<"atomic_load_umin_i8", "AMOMINU_B", XLenVT, [HasStdExtZabha]>;
200
201defm : AMOPat<"atomic_swap_i16", "AMOSWAP_H", XLenVT, [HasStdExtZabha]>;
202defm : AMOPat<"atomic_load_add_i16", "AMOADD_H", XLenVT, [HasStdExtZabha]>;
203defm : AMOPat<"atomic_load_and_i16", "AMOAND_H", XLenVT, [HasStdExtZabha]>;
204defm : AMOPat<"atomic_load_or_i16", "AMOOR_H", XLenVT, [HasStdExtZabha]>;
205defm : AMOPat<"atomic_load_xor_i16", "AMOXOR_H", XLenVT, [HasStdExtZabha]>;
206defm : AMOPat<"atomic_load_max_i16", "AMOMAX_H", XLenVT, [HasStdExtZabha]>;
207defm : AMOPat<"atomic_load_min_i16", "AMOMIN_H", XLenVT, [HasStdExtZabha]>;
208defm : AMOPat<"atomic_load_umax_i16", "AMOMAXU_H", XLenVT, [HasStdExtZabha]>;
209defm : AMOPat<"atomic_load_umin_i16", "AMOMINU_H", XLenVT, [HasStdExtZabha]>;
210
211/// AMOCAS
212
213defm : AMOCASPat<"atomic_cmp_swap_i8", "AMOCAS_B", XLenVT, [HasStdExtZabha]>;
214defm : AMOCASPat<"atomic_cmp_swap_i16", "AMOCAS_H", XLenVT, [HasStdExtZabha]>;
215