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