xref: /freebsd-src/contrib/llvm-project/llvm/lib/Target/RISCV/RISCVInstrInfoZa.td (revision 0fca6ea1d4eea4c934cfff25ac9ee8ad6fe95583)
11db9f3b2SDimitry Andric//===-- RISCVInstrInfoZa.td - RISC-V Atomic instructions ---*- tablegen -*-===//
21db9f3b2SDimitry Andric//
31db9f3b2SDimitry Andric// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
41db9f3b2SDimitry Andric// See https://llvm.org/LICENSE.txt for license information.
51db9f3b2SDimitry Andric// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
61db9f3b2SDimitry Andric//
71db9f3b2SDimitry Andric//===----------------------------------------------------------------------===//
81db9f3b2SDimitry Andric//
91db9f3b2SDimitry Andric// This file describes the RISC-V instructions from the standard atomic 'Za*'
101db9f3b2SDimitry Andric// extensions:
111db9f3b2SDimitry Andric//   - Zawrs (v1.0) : Wait-on-Reservation-Set.
121db9f3b2SDimitry Andric//   - Zacas (v1.0-rc1) : Atomic Compare-and-Swap.
13*0fca6ea1SDimitry Andric//   - Zabha (v1.0-rc1) : Byte and Halfword Atomic Memory Operations.
141db9f3b2SDimitry Andric//
151db9f3b2SDimitry Andric//===----------------------------------------------------------------------===//
161db9f3b2SDimitry Andric
171db9f3b2SDimitry Andric//===----------------------------------------------------------------------===//
181db9f3b2SDimitry Andric// Zacas (Atomic Compare-and-Swap)
191db9f3b2SDimitry Andric//===----------------------------------------------------------------------===//
201db9f3b2SDimitry Andric
21297eecfbSDimitry Andricdef GPRPairRV32Operand : AsmOperandClass {
22297eecfbSDimitry Andric  let Name = "GPRPairRV32";
23297eecfbSDimitry Andric  let ParserMethod = "parseGPRPair<false>";
24297eecfbSDimitry Andric  let PredicateMethod = "isGPRPair";
25297eecfbSDimitry Andric  let RenderMethod = "addRegOperands";
26297eecfbSDimitry Andric}
27297eecfbSDimitry Andric
28297eecfbSDimitry Andricdef GPRPairRV64Operand : AsmOperandClass {
29297eecfbSDimitry Andric  let Name = "GPRPairRV64";
30297eecfbSDimitry Andric  let ParserMethod = "parseGPRPair<true>";
31297eecfbSDimitry Andric  let PredicateMethod = "isGPRPair";
32297eecfbSDimitry Andric  let RenderMethod = "addRegOperands";
33297eecfbSDimitry Andric}
34297eecfbSDimitry Andric
35297eecfbSDimitry Andricdef GPRPairRV32 : RegisterOperand<GPRPair> {
36297eecfbSDimitry Andric  let ParserMatchClass = GPRPairRV32Operand;
37297eecfbSDimitry Andric}
38297eecfbSDimitry Andric
39297eecfbSDimitry Andricdef GPRPairRV64 : RegisterOperand<GPRPair> {
40297eecfbSDimitry Andric  let ParserMatchClass = GPRPairRV64Operand;
41297eecfbSDimitry Andric}
42297eecfbSDimitry Andric
43297eecfbSDimitry Andriclet hasSideEffects = 0, mayLoad = 1, mayStore = 1, Constraints = "$rd = $rd_wb" in
44297eecfbSDimitry Andricclass AMO_cas<bits<5> funct5, bit aq, bit rl, bits<3> funct3, string opcodestr,
45297eecfbSDimitry Andric              DAGOperand RC>
46297eecfbSDimitry Andric    : RVInstRAtomic<funct5, aq, rl, funct3, OPC_AMO,
47297eecfbSDimitry Andric                    (outs RC:$rd_wb), (ins RC:$rd, GPRMemZeroOffset:$rs1, RC:$rs2),
48297eecfbSDimitry Andric                    opcodestr, "$rd, $rs2, $rs1">;
49297eecfbSDimitry Andric
50297eecfbSDimitry Andricmulticlass AMO_cas_aq_rl<bits<5> funct5, bits<3> funct3, string opcodestr,
51297eecfbSDimitry Andric                         DAGOperand RC> {
52297eecfbSDimitry Andric  def ""     : AMO_cas<funct5, 0, 0, funct3, opcodestr, RC>;
53297eecfbSDimitry Andric  def _AQ    : AMO_cas<funct5, 1, 0, funct3, opcodestr # ".aq", RC>;
54297eecfbSDimitry Andric  def _RL    : AMO_cas<funct5, 0, 1, funct3, opcodestr # ".rl", RC>;
55297eecfbSDimitry Andric  def _AQ_RL : AMO_cas<funct5, 1, 1, funct3, opcodestr # ".aqrl", RC>;
56297eecfbSDimitry Andric}
57297eecfbSDimitry Andric
58*0fca6ea1SDimitry Andriclet Predicates = [HasStdExtZacas], IsSignExtendingOpW = 1 in {
59297eecfbSDimitry Andricdefm AMOCAS_W : AMO_cas_aq_rl<0b00101, 0b010, "amocas.w", GPR>;
601db9f3b2SDimitry Andric} // Predicates = [HasStdExtZacas]
611db9f3b2SDimitry Andric
62297eecfbSDimitry Andriclet Predicates = [HasStdExtZacas, IsRV32], DecoderNamespace = "RV32Zacas"  in {
63297eecfbSDimitry Andricdefm AMOCAS_D_RV32 : AMO_cas_aq_rl<0b00101, 0b011, "amocas.d", GPRPairRV32>;
64297eecfbSDimitry Andric} // Predicates = [HasStdExtZacas, IsRV32]
65297eecfbSDimitry Andric
661db9f3b2SDimitry Andriclet Predicates = [HasStdExtZacas, IsRV64] in {
67297eecfbSDimitry Andricdefm AMOCAS_D_RV64 : AMO_cas_aq_rl<0b00101, 0b011, "amocas.d", GPR>;
68297eecfbSDimitry Andricdefm AMOCAS_Q : AMO_cas_aq_rl<0b00101, 0b100, "amocas.q", GPRPairRV64>;
691db9f3b2SDimitry Andric} // Predicates = [HasStdExtZacas, IsRV64]
701db9f3b2SDimitry Andric
71297eecfbSDimitry Andricmulticlass AMOCASPat<string AtomicOp, string BaseInst, ValueType vt = XLenVT,
72297eecfbSDimitry Andric                     list<Predicate> ExtraPreds = []> {
73297eecfbSDimitry Andric  let Predicates = !listconcat([HasStdExtZacas, NotHasStdExtZtso], ExtraPreds) in {
74297eecfbSDimitry Andric    def : Pat<(!cast<PatFrag>(AtomicOp#"_monotonic") (vt GPR:$addr),
75297eecfbSDimitry Andric                                                     (vt GPR:$cmp),
76297eecfbSDimitry Andric                                                     (vt GPR:$new)),
77297eecfbSDimitry Andric              (!cast<RVInst>(BaseInst) GPR:$cmp, GPR:$addr, GPR:$new)>;
78297eecfbSDimitry Andric    def : Pat<(!cast<PatFrag>(AtomicOp#"_acquire") (vt GPR:$addr),
79297eecfbSDimitry Andric                                                   (vt GPR:$cmp),
80297eecfbSDimitry Andric                                                   (vt GPR:$new)),
81297eecfbSDimitry Andric              (!cast<RVInst>(BaseInst#"_AQ") GPR:$cmp, GPR:$addr, GPR:$new)>;
82297eecfbSDimitry Andric    def : Pat<(!cast<PatFrag>(AtomicOp#"_release") (vt GPR:$addr),
83297eecfbSDimitry Andric                                                   (vt GPR:$cmp),
84297eecfbSDimitry Andric                                                   (vt GPR:$new)),
85297eecfbSDimitry Andric              (!cast<RVInst>(BaseInst#"_RL") GPR:$cmp, GPR:$addr, GPR:$new)>;
86297eecfbSDimitry Andric    def : Pat<(!cast<PatFrag>(AtomicOp#"_acq_rel") (vt GPR:$addr),
87297eecfbSDimitry Andric                                                   (vt GPR:$cmp),
88297eecfbSDimitry Andric                                                   (vt GPR:$new)),
89297eecfbSDimitry Andric              (!cast<RVInst>(BaseInst#"_AQ_RL") GPR:$cmp, GPR:$addr, GPR:$new)>;
90297eecfbSDimitry Andric    def : Pat<(!cast<PatFrag>(AtomicOp#"_seq_cst") (vt GPR:$addr),
91297eecfbSDimitry Andric                                                   (vt GPR:$cmp),
92297eecfbSDimitry Andric                                                   (vt GPR:$new)),
93297eecfbSDimitry Andric              (!cast<RVInst>(BaseInst#"_AQ_RL") GPR:$cmp, GPR:$addr, GPR:$new)>;
94297eecfbSDimitry Andric  } // Predicates = !listconcat([HasStdExtZacas, NotHasStdExtZtso], ExtraPreds)
95297eecfbSDimitry Andric  let Predicates = !listconcat([HasStdExtZacas, HasStdExtZtso], ExtraPreds) in {
96297eecfbSDimitry Andric    def : Pat<(!cast<PatFrag>(AtomicOp#"_monotonic") (vt GPR:$addr),
97297eecfbSDimitry Andric                                                     (vt GPR:$cmp),
98297eecfbSDimitry Andric                                                     (vt GPR:$new)),
99297eecfbSDimitry Andric              (!cast<RVInst>(BaseInst) GPR:$cmp, GPR:$addr, GPR:$new)>;
100297eecfbSDimitry Andric    def : Pat<(!cast<PatFrag>(AtomicOp#"_acquire") (vt GPR:$addr),
101297eecfbSDimitry Andric                                                   (vt GPR:$cmp),
102297eecfbSDimitry Andric                                                   (vt GPR:$new)),
103297eecfbSDimitry Andric              (!cast<RVInst>(BaseInst) GPR:$cmp, GPR:$addr, GPR:$new)>;
104297eecfbSDimitry Andric    def : Pat<(!cast<PatFrag>(AtomicOp#"_release") (vt GPR:$addr),
105297eecfbSDimitry Andric                                                   (vt GPR:$cmp),
106297eecfbSDimitry Andric                                                   (vt GPR:$new)),
107297eecfbSDimitry Andric              (!cast<RVInst>(BaseInst) GPR:$cmp, GPR:$addr, GPR:$new)>;
108297eecfbSDimitry Andric    def : Pat<(!cast<PatFrag>(AtomicOp#"_acq_rel") (vt GPR:$addr),
109297eecfbSDimitry Andric                                                   (vt GPR:$cmp),
110297eecfbSDimitry Andric                                                   (vt GPR:$new)),
111297eecfbSDimitry Andric              (!cast<RVInst>(BaseInst) GPR:$cmp, GPR:$addr, GPR:$new)>;
112297eecfbSDimitry Andric    def : Pat<(!cast<PatFrag>(AtomicOp#"_seq_cst") (vt GPR:$addr),
113297eecfbSDimitry Andric                                                   (vt GPR:$cmp),
114297eecfbSDimitry Andric                                                   (vt GPR:$new)),
115297eecfbSDimitry Andric              (!cast<RVInst>(BaseInst) GPR:$cmp, GPR:$addr, GPR:$new)>;
116297eecfbSDimitry Andric  } // Predicates = !listconcat([HasStdExtZacas, HasStdExtZtso], ExtraPreds)
117297eecfbSDimitry Andric}
118297eecfbSDimitry Andric
119*0fca6ea1SDimitry Andricdefm : AMOCASPat<"atomic_cmp_swap_i32", "AMOCAS_W">;
120*0fca6ea1SDimitry Andricdefm : AMOCASPat<"atomic_cmp_swap_i64", "AMOCAS_D_RV64", i64, [IsRV64]>;
121297eecfbSDimitry Andric
1221db9f3b2SDimitry Andric//===----------------------------------------------------------------------===//
1231db9f3b2SDimitry Andric// Zawrs (Wait-on-Reservation-Set)
1241db9f3b2SDimitry Andric//===----------------------------------------------------------------------===//
1251db9f3b2SDimitry Andric
1261db9f3b2SDimitry Andriclet hasSideEffects = 1, mayLoad = 0, mayStore = 0 in
1271db9f3b2SDimitry Andricclass WRSInst<bits<12> funct12, string opcodestr>
1281db9f3b2SDimitry Andric    : RVInstI<0b000, OPC_SYSTEM, (outs), (ins), opcodestr, ""> {
1291db9f3b2SDimitry Andric  let rs1 = 0;
1301db9f3b2SDimitry Andric  let rd = 0;
1311db9f3b2SDimitry Andric  let imm12 = funct12;
1321db9f3b2SDimitry Andric}
1331db9f3b2SDimitry Andric
1341db9f3b2SDimitry Andriclet Predicates = [HasStdExtZawrs] in {
1351db9f3b2SDimitry Andricdef WRS_NTO : WRSInst<0b000000001101, "wrs.nto">, Sched<[]>;
1361db9f3b2SDimitry Andricdef WRS_STO : WRSInst<0b000000011101, "wrs.sto">, Sched<[]>;
1371db9f3b2SDimitry Andric} // Predicates = [HasStdExtZawrs]
138*0fca6ea1SDimitry Andric
139*0fca6ea1SDimitry Andric//===----------------------------------------------------------------------===//
140*0fca6ea1SDimitry Andric// Zabha (Byte and Halfword Atomic Memory Operations)
141*0fca6ea1SDimitry Andric//===----------------------------------------------------------------------===//
142*0fca6ea1SDimitry Andric
143*0fca6ea1SDimitry Andriclet Predicates = [HasStdExtZabha] in {
144*0fca6ea1SDimitry Andricdefm AMOSWAP_B  : AMO_rr_aq_rl<0b00001, 0b000, "amoswap.b">,
145*0fca6ea1SDimitry Andric                  Sched<[WriteAtomicB, ReadAtomicBA, ReadAtomicBD]>;
146*0fca6ea1SDimitry Andricdefm AMOADD_B   : AMO_rr_aq_rl<0b00000, 0b000, "amoadd.b">,
147*0fca6ea1SDimitry Andric                  Sched<[WriteAtomicB, ReadAtomicBA, ReadAtomicBD]>;
148*0fca6ea1SDimitry Andricdefm AMOXOR_B   : AMO_rr_aq_rl<0b00100, 0b000, "amoxor.b">,
149*0fca6ea1SDimitry Andric                  Sched<[WriteAtomicB, ReadAtomicBA, ReadAtomicBD]>;
150*0fca6ea1SDimitry Andricdefm AMOAND_B   : AMO_rr_aq_rl<0b01100, 0b000, "amoand.b">,
151*0fca6ea1SDimitry Andric                  Sched<[WriteAtomicB, ReadAtomicBA, ReadAtomicBD]>;
152*0fca6ea1SDimitry Andricdefm AMOOR_B    : AMO_rr_aq_rl<0b01000, 0b000, "amoor.b">,
153*0fca6ea1SDimitry Andric                  Sched<[WriteAtomicB, ReadAtomicBA, ReadAtomicBD]>;
154*0fca6ea1SDimitry Andricdefm AMOMIN_B   : AMO_rr_aq_rl<0b10000, 0b000, "amomin.b">,
155*0fca6ea1SDimitry Andric                  Sched<[WriteAtomicB, ReadAtomicBA, ReadAtomicBD]>;
156*0fca6ea1SDimitry Andricdefm AMOMAX_B   : AMO_rr_aq_rl<0b10100, 0b000, "amomax.b">,
157*0fca6ea1SDimitry Andric                  Sched<[WriteAtomicB, ReadAtomicBA, ReadAtomicBD]>;
158*0fca6ea1SDimitry Andricdefm AMOMINU_B  : AMO_rr_aq_rl<0b11000, 0b000, "amominu.b">,
159*0fca6ea1SDimitry Andric                  Sched<[WriteAtomicB, ReadAtomicBA, ReadAtomicBD]>;
160*0fca6ea1SDimitry Andricdefm AMOMAXU_B  : AMO_rr_aq_rl<0b11100, 0b000, "amomaxu.b">,
161*0fca6ea1SDimitry Andric                  Sched<[WriteAtomicB, ReadAtomicBA, ReadAtomicBD]>;
162*0fca6ea1SDimitry Andric
163*0fca6ea1SDimitry Andricdefm AMOSWAP_H  : AMO_rr_aq_rl<0b00001, 0b001, "amoswap.h">,
164*0fca6ea1SDimitry Andric                  Sched<[WriteAtomicH, ReadAtomicHA, ReadAtomicHD]>;
165*0fca6ea1SDimitry Andricdefm AMOADD_H   : AMO_rr_aq_rl<0b00000, 0b001, "amoadd.h">,
166*0fca6ea1SDimitry Andric                  Sched<[WriteAtomicH, ReadAtomicHA, ReadAtomicHD]>;
167*0fca6ea1SDimitry Andricdefm AMOXOR_H   : AMO_rr_aq_rl<0b00100, 0b001, "amoxor.h">,
168*0fca6ea1SDimitry Andric                  Sched<[WriteAtomicH, ReadAtomicHA, ReadAtomicHD]>;
169*0fca6ea1SDimitry Andricdefm AMOAND_H   : AMO_rr_aq_rl<0b01100, 0b001, "amoand.h">,
170*0fca6ea1SDimitry Andric                  Sched<[WriteAtomicH, ReadAtomicHA, ReadAtomicHD]>;
171*0fca6ea1SDimitry Andricdefm AMOOR_H    : AMO_rr_aq_rl<0b01000, 0b001, "amoor.h">,
172*0fca6ea1SDimitry Andric                  Sched<[WriteAtomicH, ReadAtomicHA, ReadAtomicHD]>;
173*0fca6ea1SDimitry Andricdefm AMOMIN_H   : AMO_rr_aq_rl<0b10000, 0b001, "amomin.h">,
174*0fca6ea1SDimitry Andric                  Sched<[WriteAtomicH, ReadAtomicHA, ReadAtomicHD]>;
175*0fca6ea1SDimitry Andricdefm AMOMAX_H   : AMO_rr_aq_rl<0b10100, 0b001, "amomax.h">,
176*0fca6ea1SDimitry Andric                  Sched<[WriteAtomicH, ReadAtomicHA, ReadAtomicHD]>;
177*0fca6ea1SDimitry Andricdefm AMOMINU_H  : AMO_rr_aq_rl<0b11000, 0b001, "amominu.h">,
178*0fca6ea1SDimitry Andric                  Sched<[WriteAtomicH, ReadAtomicHA, ReadAtomicHD]>;
179*0fca6ea1SDimitry Andricdefm AMOMAXU_H  : AMO_rr_aq_rl<0b11100, 0b001, "amomaxu.h">,
180*0fca6ea1SDimitry Andric                  Sched<[WriteAtomicH, ReadAtomicHA, ReadAtomicHD]>;
181*0fca6ea1SDimitry Andric}
182*0fca6ea1SDimitry Andric
183*0fca6ea1SDimitry Andric// If Zacas extension is also implemented, Zabha further provides AMOCAS.[B|H].
184*0fca6ea1SDimitry Andriclet Predicates = [HasStdExtZabha, HasStdExtZacas] in {
185*0fca6ea1SDimitry Andricdefm AMOCAS_B : AMO_cas_aq_rl<0b00101, 0b000, "amocas.b", GPR>;
186*0fca6ea1SDimitry Andricdefm AMOCAS_H : AMO_cas_aq_rl<0b00101, 0b001, "amocas.h", GPR>;
187*0fca6ea1SDimitry Andric}
188*0fca6ea1SDimitry Andric
189*0fca6ea1SDimitry Andric/// AMOs
190*0fca6ea1SDimitry Andric
191*0fca6ea1SDimitry Andricdefm : AMOPat<"atomic_swap_i8", "AMOSWAP_B", XLenVT, [HasStdExtZabha]>;
192*0fca6ea1SDimitry Andricdefm : AMOPat<"atomic_load_add_i8", "AMOADD_B", XLenVT, [HasStdExtZabha]>;
193*0fca6ea1SDimitry Andricdefm : AMOPat<"atomic_load_and_i8", "AMOAND_B", XLenVT, [HasStdExtZabha]>;
194*0fca6ea1SDimitry Andricdefm : AMOPat<"atomic_load_or_i8", "AMOOR_B", XLenVT, [HasStdExtZabha]>;
195*0fca6ea1SDimitry Andricdefm : AMOPat<"atomic_load_xor_i8", "AMOXOR_B", XLenVT, [HasStdExtZabha]>;
196*0fca6ea1SDimitry Andricdefm : AMOPat<"atomic_load_max_i8", "AMOMAX_B", XLenVT, [HasStdExtZabha]>;
197*0fca6ea1SDimitry Andricdefm : AMOPat<"atomic_load_min_i8", "AMOMIN_B", XLenVT, [HasStdExtZabha]>;
198*0fca6ea1SDimitry Andricdefm : AMOPat<"atomic_load_umax_i8", "AMOMAXU_B", XLenVT, [HasStdExtZabha]>;
199*0fca6ea1SDimitry Andricdefm : AMOPat<"atomic_load_umin_i8", "AMOMINU_B", XLenVT, [HasStdExtZabha]>;
200*0fca6ea1SDimitry Andric
201*0fca6ea1SDimitry Andricdefm : AMOPat<"atomic_swap_i16", "AMOSWAP_H", XLenVT, [HasStdExtZabha]>;
202*0fca6ea1SDimitry Andricdefm : AMOPat<"atomic_load_add_i16", "AMOADD_H", XLenVT, [HasStdExtZabha]>;
203*0fca6ea1SDimitry Andricdefm : AMOPat<"atomic_load_and_i16", "AMOAND_H", XLenVT, [HasStdExtZabha]>;
204*0fca6ea1SDimitry Andricdefm : AMOPat<"atomic_load_or_i16", "AMOOR_H", XLenVT, [HasStdExtZabha]>;
205*0fca6ea1SDimitry Andricdefm : AMOPat<"atomic_load_xor_i16", "AMOXOR_H", XLenVT, [HasStdExtZabha]>;
206*0fca6ea1SDimitry Andricdefm : AMOPat<"atomic_load_max_i16", "AMOMAX_H", XLenVT, [HasStdExtZabha]>;
207*0fca6ea1SDimitry Andricdefm : AMOPat<"atomic_load_min_i16", "AMOMIN_H", XLenVT, [HasStdExtZabha]>;
208*0fca6ea1SDimitry Andricdefm : AMOPat<"atomic_load_umax_i16", "AMOMAXU_H", XLenVT, [HasStdExtZabha]>;
209*0fca6ea1SDimitry Andricdefm : AMOPat<"atomic_load_umin_i16", "AMOMINU_H", XLenVT, [HasStdExtZabha]>;
210*0fca6ea1SDimitry Andric
211*0fca6ea1SDimitry Andric/// AMOCAS
212*0fca6ea1SDimitry Andric
213*0fca6ea1SDimitry Andricdefm : AMOCASPat<"atomic_cmp_swap_i8", "AMOCAS_B", XLenVT, [HasStdExtZabha]>;
214*0fca6ea1SDimitry Andricdefm : AMOCASPat<"atomic_cmp_swap_i16", "AMOCAS_H", XLenVT, [HasStdExtZabha]>;
215