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