diff --git a/Rakefile b/Rakefile index 7dae0168d5..aed654a78d 100755 --- a/Rakefile +++ b/Rakefile @@ -5,6 +5,9 @@ require "sorbet-runtime" T.bind(self, T.all(Rake::DSL, Object)) extend T::Sig +require 'pathname' +require 'erb' + Encoding.default_external = "UTF-8" $jobs = ENV["JOBS"].nil? ? 1 : ENV["JOBS"].to_i @@ -360,6 +363,55 @@ file "#{$resolver.std_path}/csr/Zicntr/mcountinhibit.yaml" => [ File.write(t.name, insert_warning(erb.result(binding), t.prerequisites.first)) end +# Define all acquire/release combinations +aq_rl_variants = [ + { suffix: "", aq: false, rl: false }, # base instruction + { suffix: ".aq", aq: true, rl: false }, # acquire only + { suffix: ".rl", aq: false, rl: true }, # release only + { suffix: ".aqrl", aq: true, rl: true } # both acquire and release +] + +# AMO instruction generation from layouts +%w[amoadd amoand amomax amomaxu amomin amominu amoor amoswap amoxor].each do |op| + ["b", "h", "w", "d"].each do |size| + # Determine target extension directory based on size + extension_dir = %w[b h].include?(size) ? "Zabha" : "Zaamo" + + aq_rl_variants.each do |variant| + file "#{$resolver.std_path}/inst/#{extension_dir}/#{op}.#{size}#{variant[:suffix]}.yaml" => [ + "#{$resolver.std_path}/inst/Zaamo/#{op}.SIZE.AQRL.layout", + __FILE__ + ] do |t| + aq = variant[:aq] + rl = variant[:rl] + erb = ERB.new(File.read($resolver.std_path / "inst/Zaamo/#{op}.SIZE.AQRL.layout"), trim_mode: "-") + erb.filename = "#{$resolver.std_path}/inst/Zaamo/#{op}.SIZE.AQRL.layout" + File.write(t.name, insert_warning(erb.result(binding), t.prerequisites.first)) + end + end + end +end + +# AMOCAS instruction generation from Zabha layout (supports both Zabha and Zacas) +# Zabha variants (b, h) -> generated in Zabha directory +["b", "h", "w", "d", "q" ].each do |size| + # Determine target extension directory based on size + extension_dir = %w[w d q].include?(size) ? "Zacas" : "Zabha" + + aq_rl_variants.each do |variant| + file "#{$resolver.std_path}/inst/#{extension_dir}/amocas.#{size}#{variant[:suffix]}.yaml" => [ + "#{$resolver.std_path}/inst/Zacas/amocas.SIZE.AQRL.layout", + __FILE__ + ] do |t| + aq = variant[:aq] + rl = variant[:rl] + erb = ERB.new(File.read($resolver.std_path / "inst/Zacas/amocas.SIZE.AQRL.layout"), trim_mode: "-") + erb.filename = "#{$resolver.std_path}/inst/Zacas/amocas.SIZE.AQRL.layout" + File.write(t.name, insert_warning(erb.result(binding), t.prerequisites.first)) + end + end +end + namespace :gen do desc "Generate architecture files from layouts" task :arch do @@ -386,6 +438,26 @@ namespace :gen do (0..15).each do |pmpcfg_num| Rake::Task["#{$resolver.std_path}/csr/I/pmpcfg#{pmpcfg_num}.yaml"].invoke end + + # Generate AMO instruction files + %w[amoadd amoand amomax amomaxu amomin amominu amoor amoswap amoxor].each do |op| + ["b", "h", "w", "d"].each do |size| + extension_dir = %w[b h].include?(size) ? "Zabha" : "Zaamo" + ["", ".aq", ".rl", ".aqrl"].each do |suffix| + Rake::Task["#{$resolver.std_path}/inst/#{extension_dir}/#{op}.#{size}#{suffix}.yaml"].invoke + end + end + end + + # Generate AMOCAS instruction files + ["b", "h", "w", "d", "q"].each do |size| + ["", ".aq", ".rl", ".aqrl"].each do |suffix| + # Determine target extension directory based on size + extension_dir = %w[w d q].include?(size) ? "Zacas" : "Zabha" + + Rake::Task["#{$resolver.std_path}/inst/#{extension_dir}/amocas.#{size}#{suffix}.yaml"].invoke + end + end end end diff --git a/backends/instructions_appendix/all_instructions.golden.adoc b/backends/instructions_appendix/all_instructions.golden.adoc index caf82d8485..8aab83aa5b 100644 --- a/backends/instructions_appendix/all_instructions.golden.adoc +++ b/backends/instructions_appendix/all_instructions.golden.adoc @@ -640,7 +640,7 @@ Included in:: == amoadd.b Synopsis:: -No synopsis available +Atomic fetch-and-add byte Assembly:: amoadd.b xd, xs2, (xs1) @@ -648,19 +648,151 @@ amoadd.b xd, xs2, (xs1) Encoding:: [wavedrom, ,svg,subs='attributes',width="100%"] .... -{"reg":[{"bits":7,"name": 0x2f,"type":2},{"bits":5,"name": "xd","type":4},{"bits":3,"name": 0x0,"type":2},{"bits":5,"name": "xs1","type":4},{"bits":5,"name": "xs2","type":4},{"bits":1,"name": "rl","type":4},{"bits":1,"name": "aq","type":4},{"bits":5,"name": 0x0,"type":2}]} +{"reg":[{"bits":7,"name": 0x2f,"type":2},{"bits":5,"name": "xd","type":4},{"bits":3,"name": 0x0,"type":2},{"bits":5,"name": "xs1","type":4},{"bits":5,"name": "xs2","type":4},{"bits":7,"name": 0x0,"type":2}]} .... Description:: -No description available. +Atomically: + + * Load the byte at address _xs1_ + * Write the sign-extended value into _xd_ + * Add the least-significant byte of register _xs2_ to the loaded value + * Write the result to the address in _xs1_ + + +Decode Variables:: +[width="100%", cols="1,2", options="header"] +|=== +|Variable Name |Location +|xs2 |$encoding[24:20] +|xs1 |$encoding[19:15] +|xd |$encoding[11:7] +|=== + +Included in:: +[options="autowrap,autowidth"] +|=== +| Extension | Version + +| *Zabha* | ~> 1.0.0 + +|=== + + +[#udb:doc:inst:amoadd_b_aq] +== amoadd.b.aq + +Synopsis:: +Atomic fetch-and-add byte (acquire) + +Assembly:: +amoadd.b.aq xd, xs2, (xs1) + +Encoding:: +[wavedrom, ,svg,subs='attributes',width="100%"] +.... +{"reg":[{"bits":7,"name": 0x2f,"type":2},{"bits":5,"name": "xd","type":4},{"bits":3,"name": 0x0,"type":2},{"bits":5,"name": "xs1","type":4},{"bits":5,"name": "xs2","type":4},{"bits":7,"name": 0x2,"type":2}]} +.... + +Description:: +Atomically with acquire ordering: + + * Load the byte at address _xs1_ + * Write the sign-extended value into _xd_ + * Add the least-significant byte of register _xs2_ to the loaded value + * Write the result to the address in _xs1_ + + +Decode Variables:: +[width="100%", cols="1,2", options="header"] +|=== +|Variable Name |Location +|xs2 |$encoding[24:20] +|xs1 |$encoding[19:15] +|xd |$encoding[11:7] +|=== + +Included in:: +[options="autowrap,autowidth"] +|=== +| Extension | Version + +| *Zabha* | ~> 1.0.0 + +|=== + + +[#udb:doc:inst:amoadd_b_aqrl] +== amoadd.b.aqrl + +Synopsis:: +Atomic fetch-and-add byte (acquire-release) + +Assembly:: +amoadd.b.aqrl xd, xs2, (xs1) + +Encoding:: +[wavedrom, ,svg,subs='attributes',width="100%"] +.... +{"reg":[{"bits":7,"name": 0x2f,"type":2},{"bits":5,"name": "xd","type":4},{"bits":3,"name": 0x0,"type":2},{"bits":5,"name": "xs1","type":4},{"bits":5,"name": "xs2","type":4},{"bits":7,"name": 0x3,"type":2}]} +.... + +Description:: +Atomically with acquire and release ordering: + + * Load the byte at address _xs1_ + * Write the sign-extended value into _xd_ + * Add the least-significant byte of register _xs2_ to the loaded value + * Write the result to the address in _xs1_ + + +Decode Variables:: +[width="100%", cols="1,2", options="header"] +|=== +|Variable Name |Location +|xs2 |$encoding[24:20] +|xs1 |$encoding[19:15] +|xd |$encoding[11:7] +|=== + +Included in:: +[options="autowrap,autowidth"] +|=== +| Extension | Version + +| *Zabha* | ~> 1.0.0 + +|=== + + +[#udb:doc:inst:amoadd_b_rl] +== amoadd.b.rl + +Synopsis:: +Atomic fetch-and-add byte (release) + +Assembly:: +amoadd.b.rl xd, xs2, (xs1) + +Encoding:: +[wavedrom, ,svg,subs='attributes',width="100%"] +.... +{"reg":[{"bits":7,"name": 0x2f,"type":2},{"bits":5,"name": "xd","type":4},{"bits":3,"name": 0x0,"type":2},{"bits":5,"name": "xs1","type":4},{"bits":5,"name": "xs2","type":4},{"bits":7,"name": 0x1,"type":2}]} +.... + +Description:: +Atomically with release ordering: + + * Load the byte at address _xs1_ + * Write the sign-extended value into _xd_ + * Add the least-significant byte of register _xs2_ to the loaded value + * Write the result to the address in _xs1_ Decode Variables:: [width="100%", cols="1,2", options="header"] |=== |Variable Name |Location -|aq |$encoding[26] -|rl |$encoding[25] |xs2 |$encoding[24:20] |xs1 |$encoding[19:15] |xd |$encoding[11:7] @@ -688,7 +820,7 @@ amoadd.d xd, xs2, (xs1) Encoding:: [wavedrom, ,svg,subs='attributes',width="100%"] .... -{"reg":[{"bits":7,"name": 0x2f,"type":2},{"bits":5,"name": "xd","type":4},{"bits":3,"name": 0x3,"type":2},{"bits":5,"name": "xs1","type":4},{"bits":5,"name": "xs2","type":4},{"bits":1,"name": "rl","type":4},{"bits":1,"name": "aq","type":4},{"bits":5,"name": 0x0,"type":2}]} +{"reg":[{"bits":7,"name": 0x2f,"type":2},{"bits":5,"name": "xd","type":4},{"bits":3,"name": 0x3,"type":2},{"bits":5,"name": "xs1","type":4},{"bits":5,"name": "xs2","type":4},{"bits":7,"name": 0x0,"type":2}]} .... Description:: @@ -697,15 +829,142 @@ Atomically: * Load the doubleword at address _xs1_ * Write the loaded value into _xd_ * Add the value of register _xs2_ to the loaded value - * Write the sum to the address in _xs1_ + * Write the result to the address in _xs1_ + + +Decode Variables:: +[width="100%", cols="1,2", options="header"] +|=== +|Variable Name |Location +|xs2 |$encoding[24:20] +|xs1 |$encoding[19:15] +|xd |$encoding[11:7] +|=== + +Included in:: +[options="autowrap,autowidth"] +|=== +| Extension | Version + +| *Zaamo* | ~> 1.0.0 + +|=== + + +[#udb:doc:inst:amoadd_d_aq] +== amoadd.d.aq + +Synopsis:: +Atomic fetch-and-add doubleword (acquire) + +Assembly:: +amoadd.d.aq xd, xs2, (xs1) + +Encoding:: +[wavedrom, ,svg,subs='attributes',width="100%"] +.... +{"reg":[{"bits":7,"name": 0x2f,"type":2},{"bits":5,"name": "xd","type":4},{"bits":3,"name": 0x3,"type":2},{"bits":5,"name": "xs1","type":4},{"bits":5,"name": "xs2","type":4},{"bits":7,"name": 0x2,"type":2}]} +.... + +Description:: +Atomically with acquire ordering: + + * Load the doubleword at address _xs1_ + * Write the loaded value into _xd_ + * Add the value of register _xs2_ to the loaded value + * Write the result to the address in _xs1_ + + +Decode Variables:: +[width="100%", cols="1,2", options="header"] +|=== +|Variable Name |Location +|xs2 |$encoding[24:20] +|xs1 |$encoding[19:15] +|xd |$encoding[11:7] +|=== + +Included in:: +[options="autowrap,autowidth"] +|=== +| Extension | Version + +| *Zaamo* | ~> 1.0.0 + +|=== + + +[#udb:doc:inst:amoadd_d_aqrl] +== amoadd.d.aqrl + +Synopsis:: +Atomic fetch-and-add doubleword (acquire-release) + +Assembly:: +amoadd.d.aqrl xd, xs2, (xs1) + +Encoding:: +[wavedrom, ,svg,subs='attributes',width="100%"] +.... +{"reg":[{"bits":7,"name": 0x2f,"type":2},{"bits":5,"name": "xd","type":4},{"bits":3,"name": 0x3,"type":2},{"bits":5,"name": "xs1","type":4},{"bits":5,"name": "xs2","type":4},{"bits":7,"name": 0x3,"type":2}]} +.... + +Description:: +Atomically with acquire and release ordering: + + * Load the doubleword at address _xs1_ + * Write the loaded value into _xd_ + * Add the value of register _xs2_ to the loaded value + * Write the result to the address in _xs1_ + + +Decode Variables:: +[width="100%", cols="1,2", options="header"] +|=== +|Variable Name |Location +|xs2 |$encoding[24:20] +|xs1 |$encoding[19:15] +|xd |$encoding[11:7] +|=== + +Included in:: +[options="autowrap,autowidth"] +|=== +| Extension | Version + +| *Zaamo* | ~> 1.0.0 + +|=== + + +[#udb:doc:inst:amoadd_d_rl] +== amoadd.d.rl + +Synopsis:: +Atomic fetch-and-add doubleword (release) + +Assembly:: +amoadd.d.rl xd, xs2, (xs1) + +Encoding:: +[wavedrom, ,svg,subs='attributes',width="100%"] +.... +{"reg":[{"bits":7,"name": 0x2f,"type":2},{"bits":5,"name": "xd","type":4},{"bits":3,"name": 0x3,"type":2},{"bits":5,"name": "xs1","type":4},{"bits":5,"name": "xs2","type":4},{"bits":7,"name": 0x1,"type":2}]} +.... + +Description:: +Atomically with release ordering: + + * Load the doubleword at address _xs1_ + * Write the loaded value into _xd_ + * Add the value of register _xs2_ to the loaded value + * Write the result to the address in _xs1_ Decode Variables:: [width="100%", cols="1,2", options="header"] |=== |Variable Name |Location -|aq |$encoding[26] -|rl |$encoding[25] |xs2 |$encoding[24:20] |xs1 |$encoding[19:15] |xd |$encoding[11:7] @@ -725,7 +984,7 @@ Included in:: == amoadd.h Synopsis:: -No synopsis available +Atomic fetch-and-add halfword Assembly:: amoadd.h xd, xs2, (xs1) @@ -733,19 +992,22 @@ amoadd.h xd, xs2, (xs1) Encoding:: [wavedrom, ,svg,subs='attributes',width="100%"] .... -{"reg":[{"bits":7,"name": 0x2f,"type":2},{"bits":5,"name": "xd","type":4},{"bits":3,"name": 0x1,"type":2},{"bits":5,"name": "xs1","type":4},{"bits":5,"name": "xs2","type":4},{"bits":1,"name": "rl","type":4},{"bits":1,"name": "aq","type":4},{"bits":5,"name": 0x0,"type":2}]} +{"reg":[{"bits":7,"name": 0x2f,"type":2},{"bits":5,"name": "xd","type":4},{"bits":3,"name": 0x1,"type":2},{"bits":5,"name": "xs1","type":4},{"bits":5,"name": "xs2","type":4},{"bits":7,"name": 0x0,"type":2}]} .... Description:: -No description available. +Atomically: + + * Load the halfword at address _xs1_ + * Write the sign-extended value into _xd_ + * Add the least-significant halfword of register _xs2_ to the loaded value + * Write the result to the address in _xs1_ Decode Variables:: [width="100%", cols="1,2", options="header"] |=== |Variable Name |Location -|aq |$encoding[26] -|rl |$encoding[25] |xs2 |$encoding[24:20] |xs1 |$encoding[19:15] |xd |$encoding[11:7] @@ -761,36 +1023,5065 @@ Included in:: |=== -[#udb:doc:inst:amoadd_w] -== amoadd.w +[#udb:doc:inst:amoadd_h_aq] +== amoadd.h.aq + +Synopsis:: +Atomic fetch-and-add halfword (acquire) + +Assembly:: +amoadd.h.aq xd, xs2, (xs1) + +Encoding:: +[wavedrom, ,svg,subs='attributes',width="100%"] +.... +{"reg":[{"bits":7,"name": 0x2f,"type":2},{"bits":5,"name": "xd","type":4},{"bits":3,"name": 0x1,"type":2},{"bits":5,"name": "xs1","type":4},{"bits":5,"name": "xs2","type":4},{"bits":7,"name": 0x2,"type":2}]} +.... + +Description:: +Atomically with acquire ordering: + + * Load the halfword at address _xs1_ + * Write the sign-extended value into _xd_ + * Add the least-significant halfword of register _xs2_ to the loaded value + * Write the result to the address in _xs1_ + + +Decode Variables:: +[width="100%", cols="1,2", options="header"] +|=== +|Variable Name |Location +|xs2 |$encoding[24:20] +|xs1 |$encoding[19:15] +|xd |$encoding[11:7] +|=== + +Included in:: +[options="autowrap,autowidth"] +|=== +| Extension | Version + +| *Zabha* | ~> 1.0.0 + +|=== + + +[#udb:doc:inst:amoadd_h_aqrl] +== amoadd.h.aqrl + +Synopsis:: +Atomic fetch-and-add halfword (acquire-release) + +Assembly:: +amoadd.h.aqrl xd, xs2, (xs1) + +Encoding:: +[wavedrom, ,svg,subs='attributes',width="100%"] +.... +{"reg":[{"bits":7,"name": 0x2f,"type":2},{"bits":5,"name": "xd","type":4},{"bits":3,"name": 0x1,"type":2},{"bits":5,"name": "xs1","type":4},{"bits":5,"name": "xs2","type":4},{"bits":7,"name": 0x3,"type":2}]} +.... + +Description:: +Atomically with acquire and release ordering: + + * Load the halfword at address _xs1_ + * Write the sign-extended value into _xd_ + * Add the least-significant halfword of register _xs2_ to the loaded value + * Write the result to the address in _xs1_ + + +Decode Variables:: +[width="100%", cols="1,2", options="header"] +|=== +|Variable Name |Location +|xs2 |$encoding[24:20] +|xs1 |$encoding[19:15] +|xd |$encoding[11:7] +|=== + +Included in:: +[options="autowrap,autowidth"] +|=== +| Extension | Version + +| *Zabha* | ~> 1.0.0 + +|=== + + +[#udb:doc:inst:amoadd_h_rl] +== amoadd.h.rl + +Synopsis:: +Atomic fetch-and-add halfword (release) + +Assembly:: +amoadd.h.rl xd, xs2, (xs1) + +Encoding:: +[wavedrom, ,svg,subs='attributes',width="100%"] +.... +{"reg":[{"bits":7,"name": 0x2f,"type":2},{"bits":5,"name": "xd","type":4},{"bits":3,"name": 0x1,"type":2},{"bits":5,"name": "xs1","type":4},{"bits":5,"name": "xs2","type":4},{"bits":7,"name": 0x1,"type":2}]} +.... + +Description:: +Atomically with release ordering: + + * Load the halfword at address _xs1_ + * Write the sign-extended value into _xd_ + * Add the least-significant halfword of register _xs2_ to the loaded value + * Write the result to the address in _xs1_ + + +Decode Variables:: +[width="100%", cols="1,2", options="header"] +|=== +|Variable Name |Location +|xs2 |$encoding[24:20] +|xs1 |$encoding[19:15] +|xd |$encoding[11:7] +|=== + +Included in:: +[options="autowrap,autowidth"] +|=== +| Extension | Version + +| *Zabha* | ~> 1.0.0 + +|=== + + +[#udb:doc:inst:amoadd_w] +== amoadd.w + +Synopsis:: +Atomic fetch-and-add word + +Assembly:: +amoadd.w xd, xs2, (xs1) + +Encoding:: +[wavedrom, ,svg,subs='attributes',width="100%"] +.... +{"reg":[{"bits":7,"name": 0x2f,"type":2},{"bits":5,"name": "xd","type":4},{"bits":3,"name": 0x2,"type":2},{"bits":5,"name": "xs1","type":4},{"bits":5,"name": "xs2","type":4},{"bits":7,"name": 0x0,"type":2}]} +.... + +Description:: +Atomically: + + * Load the word at address _xs1_ + * Write the sign-extended value into _xd_ + * Add the least-significant word of register _xs2_ to the loaded value + * Write the result to the address in _xs1_ + + +Decode Variables:: +[width="100%", cols="1,2", options="header"] +|=== +|Variable Name |Location +|xs2 |$encoding[24:20] +|xs1 |$encoding[19:15] +|xd |$encoding[11:7] +|=== + +Included in:: +[options="autowrap,autowidth"] +|=== +| Extension | Version + +| *Zaamo* | ~> 1.0.0 + +|=== + + +[#udb:doc:inst:amoadd_w_aq] +== amoadd.w.aq + +Synopsis:: +Atomic fetch-and-add word (acquire) + +Assembly:: +amoadd.w.aq xd, xs2, (xs1) + +Encoding:: +[wavedrom, ,svg,subs='attributes',width="100%"] +.... +{"reg":[{"bits":7,"name": 0x2f,"type":2},{"bits":5,"name": "xd","type":4},{"bits":3,"name": 0x2,"type":2},{"bits":5,"name": "xs1","type":4},{"bits":5,"name": "xs2","type":4},{"bits":7,"name": 0x2,"type":2}]} +.... + +Description:: +Atomically with acquire ordering: + + * Load the word at address _xs1_ + * Write the sign-extended value into _xd_ + * Add the least-significant word of register _xs2_ to the loaded value + * Write the result to the address in _xs1_ + + +Decode Variables:: +[width="100%", cols="1,2", options="header"] +|=== +|Variable Name |Location +|xs2 |$encoding[24:20] +|xs1 |$encoding[19:15] +|xd |$encoding[11:7] +|=== + +Included in:: +[options="autowrap,autowidth"] +|=== +| Extension | Version + +| *Zaamo* | ~> 1.0.0 + +|=== + + +[#udb:doc:inst:amoadd_w_aqrl] +== amoadd.w.aqrl + +Synopsis:: +Atomic fetch-and-add word (acquire-release) + +Assembly:: +amoadd.w.aqrl xd, xs2, (xs1) + +Encoding:: +[wavedrom, ,svg,subs='attributes',width="100%"] +.... +{"reg":[{"bits":7,"name": 0x2f,"type":2},{"bits":5,"name": "xd","type":4},{"bits":3,"name": 0x2,"type":2},{"bits":5,"name": "xs1","type":4},{"bits":5,"name": "xs2","type":4},{"bits":7,"name": 0x3,"type":2}]} +.... + +Description:: +Atomically with acquire and release ordering: + + * Load the word at address _xs1_ + * Write the sign-extended value into _xd_ + * Add the least-significant word of register _xs2_ to the loaded value + * Write the result to the address in _xs1_ + + +Decode Variables:: +[width="100%", cols="1,2", options="header"] +|=== +|Variable Name |Location +|xs2 |$encoding[24:20] +|xs1 |$encoding[19:15] +|xd |$encoding[11:7] +|=== + +Included in:: +[options="autowrap,autowidth"] +|=== +| Extension | Version + +| *Zaamo* | ~> 1.0.0 + +|=== + + +[#udb:doc:inst:amoadd_w_rl] +== amoadd.w.rl + +Synopsis:: +Atomic fetch-and-add word (release) + +Assembly:: +amoadd.w.rl xd, xs2, (xs1) + +Encoding:: +[wavedrom, ,svg,subs='attributes',width="100%"] +.... +{"reg":[{"bits":7,"name": 0x2f,"type":2},{"bits":5,"name": "xd","type":4},{"bits":3,"name": 0x2,"type":2},{"bits":5,"name": "xs1","type":4},{"bits":5,"name": "xs2","type":4},{"bits":7,"name": 0x1,"type":2}]} +.... + +Description:: +Atomically with release ordering: + + * Load the word at address _xs1_ + * Write the sign-extended value into _xd_ + * Add the least-significant word of register _xs2_ to the loaded value + * Write the result to the address in _xs1_ + + +Decode Variables:: +[width="100%", cols="1,2", options="header"] +|=== +|Variable Name |Location +|xs2 |$encoding[24:20] +|xs1 |$encoding[19:15] +|xd |$encoding[11:7] +|=== + +Included in:: +[options="autowrap,autowidth"] +|=== +| Extension | Version + +| *Zaamo* | ~> 1.0.0 + +|=== + + +[#udb:doc:inst:amoand_b] +== amoand.b + +Synopsis:: +Atomic fetch-and-and byte + +Assembly:: +amoand.b xd, xs2, (xs1) + +Encoding:: +[wavedrom, ,svg,subs='attributes',width="100%"] +.... +{"reg":[{"bits":7,"name": 0x2f,"type":2},{"bits":5,"name": "xd","type":4},{"bits":3,"name": 0x0,"type":2},{"bits":5,"name": "xs1","type":4},{"bits":5,"name": "xs2","type":4},{"bits":7,"name": 0x30,"type":2}]} +.... + +Description:: +Atomically: + + * Load the byte at address _xs1_ + * Write the sign-extended value into _xd_ + * AND the least-significant byte of register _xs2_ to the loaded value + * Write the result to the address in _xs1_ + + +Decode Variables:: +[width="100%", cols="1,2", options="header"] +|=== +|Variable Name |Location +|xs2 |$encoding[24:20] +|xs1 |$encoding[19:15] +|xd |$encoding[11:7] +|=== + +Included in:: +[options="autowrap,autowidth"] +|=== +| Extension | Version + +| *Zabha* | ~> 1.0.0 + +|=== + + +[#udb:doc:inst:amoand_b_aq] +== amoand.b.aq + +Synopsis:: +Atomic fetch-and-and byte (acquire) + +Assembly:: +amoand.b.aq xd, xs2, (xs1) + +Encoding:: +[wavedrom, ,svg,subs='attributes',width="100%"] +.... +{"reg":[{"bits":7,"name": 0x2f,"type":2},{"bits":5,"name": "xd","type":4},{"bits":3,"name": 0x0,"type":2},{"bits":5,"name": "xs1","type":4},{"bits":5,"name": "xs2","type":4},{"bits":7,"name": 0x32,"type":2}]} +.... + +Description:: +Atomically with acquire ordering: + + * Load the byte at address _xs1_ + * Write the sign-extended value into _xd_ + * AND the least-significant byte of register _xs2_ to the loaded value + * Write the result to the address in _xs1_ + + +Decode Variables:: +[width="100%", cols="1,2", options="header"] +|=== +|Variable Name |Location +|xs2 |$encoding[24:20] +|xs1 |$encoding[19:15] +|xd |$encoding[11:7] +|=== + +Included in:: +[options="autowrap,autowidth"] +|=== +| Extension | Version + +| *Zabha* | ~> 1.0.0 + +|=== + + +[#udb:doc:inst:amoand_b_aqrl] +== amoand.b.aqrl + +Synopsis:: +Atomic fetch-and-and byte (acquire-release) + +Assembly:: +amoand.b.aqrl xd, xs2, (xs1) + +Encoding:: +[wavedrom, ,svg,subs='attributes',width="100%"] +.... +{"reg":[{"bits":7,"name": 0x2f,"type":2},{"bits":5,"name": "xd","type":4},{"bits":3,"name": 0x0,"type":2},{"bits":5,"name": "xs1","type":4},{"bits":5,"name": "xs2","type":4},{"bits":7,"name": 0x33,"type":2}]} +.... + +Description:: +Atomically with acquire and release ordering: + + * Load the byte at address _xs1_ + * Write the sign-extended value into _xd_ + * AND the least-significant byte of register _xs2_ to the loaded value + * Write the result to the address in _xs1_ + + +Decode Variables:: +[width="100%", cols="1,2", options="header"] +|=== +|Variable Name |Location +|xs2 |$encoding[24:20] +|xs1 |$encoding[19:15] +|xd |$encoding[11:7] +|=== + +Included in:: +[options="autowrap,autowidth"] +|=== +| Extension | Version + +| *Zabha* | ~> 1.0.0 + +|=== + + +[#udb:doc:inst:amoand_b_rl] +== amoand.b.rl + +Synopsis:: +Atomic fetch-and-and byte (release) + +Assembly:: +amoand.b.rl xd, xs2, (xs1) + +Encoding:: +[wavedrom, ,svg,subs='attributes',width="100%"] +.... +{"reg":[{"bits":7,"name": 0x2f,"type":2},{"bits":5,"name": "xd","type":4},{"bits":3,"name": 0x0,"type":2},{"bits":5,"name": "xs1","type":4},{"bits":5,"name": "xs2","type":4},{"bits":7,"name": 0x31,"type":2}]} +.... + +Description:: +Atomically with release ordering: + + * Load the byte at address _xs1_ + * Write the sign-extended value into _xd_ + * AND the least-significant byte of register _xs2_ to the loaded value + * Write the result to the address in _xs1_ + + +Decode Variables:: +[width="100%", cols="1,2", options="header"] +|=== +|Variable Name |Location +|xs2 |$encoding[24:20] +|xs1 |$encoding[19:15] +|xd |$encoding[11:7] +|=== + +Included in:: +[options="autowrap,autowidth"] +|=== +| Extension | Version + +| *Zabha* | ~> 1.0.0 + +|=== + + +[#udb:doc:inst:amoand_d] +== amoand.d + +Synopsis:: +Atomic fetch-and-and doubleword + +Assembly:: +amoand.d xd, xs2, (xs1) + +Encoding:: +[wavedrom, ,svg,subs='attributes',width="100%"] +.... +{"reg":[{"bits":7,"name": 0x2f,"type":2},{"bits":5,"name": "xd","type":4},{"bits":3,"name": 0x3,"type":2},{"bits":5,"name": "xs1","type":4},{"bits":5,"name": "xs2","type":4},{"bits":7,"name": 0x30,"type":2}]} +.... + +Description:: +Atomically: + + * Load the doubleword at address _xs1_ + * Write the loaded value into _xd_ + * AND the value of register _xs2_ to the loaded value + * Write the result to the address in _xs1_ + + +Decode Variables:: +[width="100%", cols="1,2", options="header"] +|=== +|Variable Name |Location +|xs2 |$encoding[24:20] +|xs1 |$encoding[19:15] +|xd |$encoding[11:7] +|=== + +Included in:: +[options="autowrap,autowidth"] +|=== +| Extension | Version + +| *Zaamo* | ~> 1.0.0 + +|=== + + +[#udb:doc:inst:amoand_d_aq] +== amoand.d.aq + +Synopsis:: +Atomic fetch-and-and doubleword (acquire) + +Assembly:: +amoand.d.aq xd, xs2, (xs1) + +Encoding:: +[wavedrom, ,svg,subs='attributes',width="100%"] +.... +{"reg":[{"bits":7,"name": 0x2f,"type":2},{"bits":5,"name": "xd","type":4},{"bits":3,"name": 0x3,"type":2},{"bits":5,"name": "xs1","type":4},{"bits":5,"name": "xs2","type":4},{"bits":7,"name": 0x32,"type":2}]} +.... + +Description:: +Atomically with acquire ordering: + + * Load the doubleword at address _xs1_ + * Write the loaded value into _xd_ + * AND the value of register _xs2_ to the loaded value + * Write the result to the address in _xs1_ + + +Decode Variables:: +[width="100%", cols="1,2", options="header"] +|=== +|Variable Name |Location +|xs2 |$encoding[24:20] +|xs1 |$encoding[19:15] +|xd |$encoding[11:7] +|=== + +Included in:: +[options="autowrap,autowidth"] +|=== +| Extension | Version + +| *Zaamo* | ~> 1.0.0 + +|=== + + +[#udb:doc:inst:amoand_d_aqrl] +== amoand.d.aqrl + +Synopsis:: +Atomic fetch-and-and doubleword (acquire-release) + +Assembly:: +amoand.d.aqrl xd, xs2, (xs1) + +Encoding:: +[wavedrom, ,svg,subs='attributes',width="100%"] +.... +{"reg":[{"bits":7,"name": 0x2f,"type":2},{"bits":5,"name": "xd","type":4},{"bits":3,"name": 0x3,"type":2},{"bits":5,"name": "xs1","type":4},{"bits":5,"name": "xs2","type":4},{"bits":7,"name": 0x33,"type":2}]} +.... + +Description:: +Atomically with acquire and release ordering: + + * Load the doubleword at address _xs1_ + * Write the loaded value into _xd_ + * AND the value of register _xs2_ to the loaded value + * Write the result to the address in _xs1_ + + +Decode Variables:: +[width="100%", cols="1,2", options="header"] +|=== +|Variable Name |Location +|xs2 |$encoding[24:20] +|xs1 |$encoding[19:15] +|xd |$encoding[11:7] +|=== + +Included in:: +[options="autowrap,autowidth"] +|=== +| Extension | Version + +| *Zaamo* | ~> 1.0.0 + +|=== + + +[#udb:doc:inst:amoand_d_rl] +== amoand.d.rl + +Synopsis:: +Atomic fetch-and-and doubleword (release) + +Assembly:: +amoand.d.rl xd, xs2, (xs1) + +Encoding:: +[wavedrom, ,svg,subs='attributes',width="100%"] +.... +{"reg":[{"bits":7,"name": 0x2f,"type":2},{"bits":5,"name": "xd","type":4},{"bits":3,"name": 0x3,"type":2},{"bits":5,"name": "xs1","type":4},{"bits":5,"name": "xs2","type":4},{"bits":7,"name": 0x31,"type":2}]} +.... + +Description:: +Atomically with release ordering: + + * Load the doubleword at address _xs1_ + * Write the loaded value into _xd_ + * AND the value of register _xs2_ to the loaded value + * Write the result to the address in _xs1_ + + +Decode Variables:: +[width="100%", cols="1,2", options="header"] +|=== +|Variable Name |Location +|xs2 |$encoding[24:20] +|xs1 |$encoding[19:15] +|xd |$encoding[11:7] +|=== + +Included in:: +[options="autowrap,autowidth"] +|=== +| Extension | Version + +| *Zaamo* | ~> 1.0.0 + +|=== + + +[#udb:doc:inst:amoand_h] +== amoand.h + +Synopsis:: +Atomic fetch-and-and halfword + +Assembly:: +amoand.h xd, xs2, (xs1) + +Encoding:: +[wavedrom, ,svg,subs='attributes',width="100%"] +.... +{"reg":[{"bits":7,"name": 0x2f,"type":2},{"bits":5,"name": "xd","type":4},{"bits":3,"name": 0x1,"type":2},{"bits":5,"name": "xs1","type":4},{"bits":5,"name": "xs2","type":4},{"bits":7,"name": 0x30,"type":2}]} +.... + +Description:: +Atomically: + + * Load the halfword at address _xs1_ + * Write the sign-extended value into _xd_ + * AND the least-significant halfword of register _xs2_ to the loaded value + * Write the result to the address in _xs1_ + + +Decode Variables:: +[width="100%", cols="1,2", options="header"] +|=== +|Variable Name |Location +|xs2 |$encoding[24:20] +|xs1 |$encoding[19:15] +|xd |$encoding[11:7] +|=== + +Included in:: +[options="autowrap,autowidth"] +|=== +| Extension | Version + +| *Zabha* | ~> 1.0.0 + +|=== + + +[#udb:doc:inst:amoand_h_aq] +== amoand.h.aq + +Synopsis:: +Atomic fetch-and-and halfword (acquire) + +Assembly:: +amoand.h.aq xd, xs2, (xs1) + +Encoding:: +[wavedrom, ,svg,subs='attributes',width="100%"] +.... +{"reg":[{"bits":7,"name": 0x2f,"type":2},{"bits":5,"name": "xd","type":4},{"bits":3,"name": 0x1,"type":2},{"bits":5,"name": "xs1","type":4},{"bits":5,"name": "xs2","type":4},{"bits":7,"name": 0x32,"type":2}]} +.... + +Description:: +Atomically with acquire ordering: + + * Load the halfword at address _xs1_ + * Write the sign-extended value into _xd_ + * AND the least-significant halfword of register _xs2_ to the loaded value + * Write the result to the address in _xs1_ + + +Decode Variables:: +[width="100%", cols="1,2", options="header"] +|=== +|Variable Name |Location +|xs2 |$encoding[24:20] +|xs1 |$encoding[19:15] +|xd |$encoding[11:7] +|=== + +Included in:: +[options="autowrap,autowidth"] +|=== +| Extension | Version + +| *Zabha* | ~> 1.0.0 + +|=== + + +[#udb:doc:inst:amoand_h_aqrl] +== amoand.h.aqrl + +Synopsis:: +Atomic fetch-and-and halfword (acquire-release) + +Assembly:: +amoand.h.aqrl xd, xs2, (xs1) + +Encoding:: +[wavedrom, ,svg,subs='attributes',width="100%"] +.... +{"reg":[{"bits":7,"name": 0x2f,"type":2},{"bits":5,"name": "xd","type":4},{"bits":3,"name": 0x1,"type":2},{"bits":5,"name": "xs1","type":4},{"bits":5,"name": "xs2","type":4},{"bits":7,"name": 0x33,"type":2}]} +.... + +Description:: +Atomically with acquire and release ordering: + + * Load the halfword at address _xs1_ + * Write the sign-extended value into _xd_ + * AND the least-significant halfword of register _xs2_ to the loaded value + * Write the result to the address in _xs1_ + + +Decode Variables:: +[width="100%", cols="1,2", options="header"] +|=== +|Variable Name |Location +|xs2 |$encoding[24:20] +|xs1 |$encoding[19:15] +|xd |$encoding[11:7] +|=== + +Included in:: +[options="autowrap,autowidth"] +|=== +| Extension | Version + +| *Zabha* | ~> 1.0.0 + +|=== + + +[#udb:doc:inst:amoand_h_rl] +== amoand.h.rl + +Synopsis:: +Atomic fetch-and-and halfword (release) + +Assembly:: +amoand.h.rl xd, xs2, (xs1) + +Encoding:: +[wavedrom, ,svg,subs='attributes',width="100%"] +.... +{"reg":[{"bits":7,"name": 0x2f,"type":2},{"bits":5,"name": "xd","type":4},{"bits":3,"name": 0x1,"type":2},{"bits":5,"name": "xs1","type":4},{"bits":5,"name": "xs2","type":4},{"bits":7,"name": 0x31,"type":2}]} +.... + +Description:: +Atomically with release ordering: + + * Load the halfword at address _xs1_ + * Write the sign-extended value into _xd_ + * AND the least-significant halfword of register _xs2_ to the loaded value + * Write the result to the address in _xs1_ + + +Decode Variables:: +[width="100%", cols="1,2", options="header"] +|=== +|Variable Name |Location +|xs2 |$encoding[24:20] +|xs1 |$encoding[19:15] +|xd |$encoding[11:7] +|=== + +Included in:: +[options="autowrap,autowidth"] +|=== +| Extension | Version + +| *Zabha* | ~> 1.0.0 + +|=== + + +[#udb:doc:inst:amoand_w] +== amoand.w + +Synopsis:: +Atomic fetch-and-and word + +Assembly:: +amoand.w xd, xs2, (xs1) + +Encoding:: +[wavedrom, ,svg,subs='attributes',width="100%"] +.... +{"reg":[{"bits":7,"name": 0x2f,"type":2},{"bits":5,"name": "xd","type":4},{"bits":3,"name": 0x2,"type":2},{"bits":5,"name": "xs1","type":4},{"bits":5,"name": "xs2","type":4},{"bits":7,"name": 0x30,"type":2}]} +.... + +Description:: +Atomically: + + * Load the word at address _xs1_ + * Write the sign-extended value into _xd_ + * AND the least-significant word of register _xs2_ to the loaded value + * Write the result to the address in _xs1_ + + +Decode Variables:: +[width="100%", cols="1,2", options="header"] +|=== +|Variable Name |Location +|xs2 |$encoding[24:20] +|xs1 |$encoding[19:15] +|xd |$encoding[11:7] +|=== + +Included in:: +[options="autowrap,autowidth"] +|=== +| Extension | Version + +| *Zaamo* | ~> 1.0.0 + +|=== + + +[#udb:doc:inst:amoand_w_aq] +== amoand.w.aq + +Synopsis:: +Atomic fetch-and-and word (acquire) + +Assembly:: +amoand.w.aq xd, xs2, (xs1) + +Encoding:: +[wavedrom, ,svg,subs='attributes',width="100%"] +.... +{"reg":[{"bits":7,"name": 0x2f,"type":2},{"bits":5,"name": "xd","type":4},{"bits":3,"name": 0x2,"type":2},{"bits":5,"name": "xs1","type":4},{"bits":5,"name": "xs2","type":4},{"bits":7,"name": 0x32,"type":2}]} +.... + +Description:: +Atomically with acquire ordering: + + * Load the word at address _xs1_ + * Write the sign-extended value into _xd_ + * AND the least-significant word of register _xs2_ to the loaded value + * Write the result to the address in _xs1_ + + +Decode Variables:: +[width="100%", cols="1,2", options="header"] +|=== +|Variable Name |Location +|xs2 |$encoding[24:20] +|xs1 |$encoding[19:15] +|xd |$encoding[11:7] +|=== + +Included in:: +[options="autowrap,autowidth"] +|=== +| Extension | Version + +| *Zaamo* | ~> 1.0.0 + +|=== + + +[#udb:doc:inst:amoand_w_aqrl] +== amoand.w.aqrl + +Synopsis:: +Atomic fetch-and-and word (acquire-release) + +Assembly:: +amoand.w.aqrl xd, xs2, (xs1) + +Encoding:: +[wavedrom, ,svg,subs='attributes',width="100%"] +.... +{"reg":[{"bits":7,"name": 0x2f,"type":2},{"bits":5,"name": "xd","type":4},{"bits":3,"name": 0x2,"type":2},{"bits":5,"name": "xs1","type":4},{"bits":5,"name": "xs2","type":4},{"bits":7,"name": 0x33,"type":2}]} +.... + +Description:: +Atomically with acquire and release ordering: + + * Load the word at address _xs1_ + * Write the sign-extended value into _xd_ + * AND the least-significant word of register _xs2_ to the loaded value + * Write the result to the address in _xs1_ + + +Decode Variables:: +[width="100%", cols="1,2", options="header"] +|=== +|Variable Name |Location +|xs2 |$encoding[24:20] +|xs1 |$encoding[19:15] +|xd |$encoding[11:7] +|=== + +Included in:: +[options="autowrap,autowidth"] +|=== +| Extension | Version + +| *Zaamo* | ~> 1.0.0 + +|=== + + +[#udb:doc:inst:amoand_w_rl] +== amoand.w.rl + +Synopsis:: +Atomic fetch-and-and word (release) + +Assembly:: +amoand.w.rl xd, xs2, (xs1) + +Encoding:: +[wavedrom, ,svg,subs='attributes',width="100%"] +.... +{"reg":[{"bits":7,"name": 0x2f,"type":2},{"bits":5,"name": "xd","type":4},{"bits":3,"name": 0x2,"type":2},{"bits":5,"name": "xs1","type":4},{"bits":5,"name": "xs2","type":4},{"bits":7,"name": 0x31,"type":2}]} +.... + +Description:: +Atomically with release ordering: + + * Load the word at address _xs1_ + * Write the sign-extended value into _xd_ + * AND the least-significant word of register _xs2_ to the loaded value + * Write the result to the address in _xs1_ + + +Decode Variables:: +[width="100%", cols="1,2", options="header"] +|=== +|Variable Name |Location +|xs2 |$encoding[24:20] +|xs1 |$encoding[19:15] +|xd |$encoding[11:7] +|=== + +Included in:: +[options="autowrap,autowidth"] +|=== +| Extension | Version + +| *Zaamo* | ~> 1.0.0 + +|=== + + +[#udb:doc:inst:amocas_b] +== amocas.b + +Synopsis:: +Atomic compare-and-swap byte + +Assembly:: +amocas.b xd, xs2, (xs1) + +Encoding:: +[wavedrom, ,svg,subs='attributes',width="100%"] +.... +{"reg":[{"bits":7,"name": 0x2f,"type":2},{"bits":5,"name": "xd","type":4},{"bits":3,"name": 0x0,"type":2},{"bits":5,"name": "xs1","type":4},{"bits":5,"name": "xs2","type":4},{"bits":7,"name": 0x14,"type":2}]} +.... + +Description:: +Atomically: + + * Load the byte at address _xs1_ + * Write the sign-extended value into _xd_ + * Compare the loaded value with the least-significant byte of register _xs2_ + * If equal, write the least-significant byte of register _xs2+1_ to the address in _xs1_ + + +Decode Variables:: +[width="100%", cols="1,2", options="header"] +|=== +|Variable Name |Location +|xs2 |$encoding[24:20] +|xs1 |$encoding[19:15] +|xd |$encoding[11:7] +|=== + +Included in:: +[options="autowrap,autowidth"] +|=== +| Extension | Version + +| *Zabha* | ~> 1.0.0 + +|=== + + +[#udb:doc:inst:amocas_b_aq] +== amocas.b.aq + +Synopsis:: +Atomic compare-and-swap byte (acquire) + +Assembly:: +amocas.b.aq xd, xs2, (xs1) + +Encoding:: +[wavedrom, ,svg,subs='attributes',width="100%"] +.... +{"reg":[{"bits":7,"name": 0x2f,"type":2},{"bits":5,"name": "xd","type":4},{"bits":3,"name": 0x0,"type":2},{"bits":5,"name": "xs1","type":4},{"bits":5,"name": "xs2","type":4},{"bits":7,"name": 0x16,"type":2}]} +.... + +Description:: +Atomically with acquire ordering: + + * Load the byte at address _xs1_ + * Write the sign-extended value into _xd_ + * Compare the loaded value with the least-significant byte of register _xs2_ + * If equal, write the least-significant byte of register _xs2+1_ to the address in _xs1_ + + +Decode Variables:: +[width="100%", cols="1,2", options="header"] +|=== +|Variable Name |Location +|xs2 |$encoding[24:20] +|xs1 |$encoding[19:15] +|xd |$encoding[11:7] +|=== + +Included in:: +[options="autowrap,autowidth"] +|=== +| Extension | Version + +| *Zabha* | ~> 1.0.0 + +|=== + + +[#udb:doc:inst:amocas_b_aqrl] +== amocas.b.aqrl + +Synopsis:: +Atomic compare-and-swap byte (acquire-release) + +Assembly:: +amocas.b.aqrl xd, xs2, (xs1) + +Encoding:: +[wavedrom, ,svg,subs='attributes',width="100%"] +.... +{"reg":[{"bits":7,"name": 0x2f,"type":2},{"bits":5,"name": "xd","type":4},{"bits":3,"name": 0x0,"type":2},{"bits":5,"name": "xs1","type":4},{"bits":5,"name": "xs2","type":4},{"bits":7,"name": 0x17,"type":2}]} +.... + +Description:: +Atomically with acquire and release ordering: + + * Load the byte at address _xs1_ + * Write the sign-extended value into _xd_ + * Compare the loaded value with the least-significant byte of register _xs2_ + * If equal, write the least-significant byte of register _xs2+1_ to the address in _xs1_ + + +Decode Variables:: +[width="100%", cols="1,2", options="header"] +|=== +|Variable Name |Location +|xs2 |$encoding[24:20] +|xs1 |$encoding[19:15] +|xd |$encoding[11:7] +|=== + +Included in:: +[options="autowrap,autowidth"] +|=== +| Extension | Version + +| *Zabha* | ~> 1.0.0 + +|=== + + +[#udb:doc:inst:amocas_b_rl] +== amocas.b.rl + +Synopsis:: +Atomic compare-and-swap byte (release) + +Assembly:: +amocas.b.rl xd, xs2, (xs1) + +Encoding:: +[wavedrom, ,svg,subs='attributes',width="100%"] +.... +{"reg":[{"bits":7,"name": 0x2f,"type":2},{"bits":5,"name": "xd","type":4},{"bits":3,"name": 0x0,"type":2},{"bits":5,"name": "xs1","type":4},{"bits":5,"name": "xs2","type":4},{"bits":7,"name": 0x15,"type":2}]} +.... + +Description:: +Atomically with release ordering: + + * Load the byte at address _xs1_ + * Write the sign-extended value into _xd_ + * Compare the loaded value with the least-significant byte of register _xs2_ + * If equal, write the least-significant byte of register _xs2+1_ to the address in _xs1_ + + +Decode Variables:: +[width="100%", cols="1,2", options="header"] +|=== +|Variable Name |Location +|xs2 |$encoding[24:20] +|xs1 |$encoding[19:15] +|xd |$encoding[11:7] +|=== + +Included in:: +[options="autowrap,autowidth"] +|=== +| Extension | Version + +| *Zabha* | ~> 1.0.0 + +|=== + + +[#udb:doc:inst:amocas_d] +== amocas.d + +Synopsis:: +Atomic compare-and-swap doubleword + +Assembly:: +amocas.d xd, xs2, (xs1) + +Encoding:: +[wavedrom, ,svg,subs='attributes',width="100%"] +.... +{"reg":[{"bits":7,"name": 0x2f,"type":2},{"bits":5,"name": "xd","type":4},{"bits":3,"name": 0x3,"type":2},{"bits":5,"name": "xs1","type":4},{"bits":5,"name": "xs2","type":4},{"bits":7,"name": 0x14,"type":2}]} +.... + +Description:: +Atomically: + + * Load the doubleword at address _xs1_ + * Write the loaded value into _xd_ + * Compare the loaded value with the value of register _xs2_ + * If equal, write the value of register _xs2+1_ to the address in _xs1_ + + +Decode Variables:: +[width="100%", cols="1,2", options="header"] +|=== +|Variable Name |Location +|xs2 |$encoding[24:20] +|xs1 |$encoding[19:15] +|xd |$encoding[11:7] +|=== + +Included in:: +[options="autowrap,autowidth"] +|=== +| Extension | Version + +| *Zacas* | ~> 1.0.0 + +|=== + + +[#udb:doc:inst:amocas_d_aq] +== amocas.d.aq + +Synopsis:: +Atomic compare-and-swap doubleword (acquire) + +Assembly:: +amocas.d.aq xd, xs2, (xs1) + +Encoding:: +[wavedrom, ,svg,subs='attributes',width="100%"] +.... +{"reg":[{"bits":7,"name": 0x2f,"type":2},{"bits":5,"name": "xd","type":4},{"bits":3,"name": 0x3,"type":2},{"bits":5,"name": "xs1","type":4},{"bits":5,"name": "xs2","type":4},{"bits":7,"name": 0x16,"type":2}]} +.... + +Description:: +Atomically with acquire ordering: + + * Load the doubleword at address _xs1_ + * Write the loaded value into _xd_ + * Compare the loaded value with the value of register _xs2_ + * If equal, write the value of register _xs2+1_ to the address in _xs1_ + + +Decode Variables:: +[width="100%", cols="1,2", options="header"] +|=== +|Variable Name |Location +|xs2 |$encoding[24:20] +|xs1 |$encoding[19:15] +|xd |$encoding[11:7] +|=== + +Included in:: +[options="autowrap,autowidth"] +|=== +| Extension | Version + +| *Zacas* | ~> 1.0.0 + +|=== + + +[#udb:doc:inst:amocas_d_aqrl] +== amocas.d.aqrl + +Synopsis:: +Atomic compare-and-swap doubleword (acquire-release) + +Assembly:: +amocas.d.aqrl xd, xs2, (xs1) + +Encoding:: +[wavedrom, ,svg,subs='attributes',width="100%"] +.... +{"reg":[{"bits":7,"name": 0x2f,"type":2},{"bits":5,"name": "xd","type":4},{"bits":3,"name": 0x3,"type":2},{"bits":5,"name": "xs1","type":4},{"bits":5,"name": "xs2","type":4},{"bits":7,"name": 0x17,"type":2}]} +.... + +Description:: +Atomically with acquire and release ordering: + + * Load the doubleword at address _xs1_ + * Write the loaded value into _xd_ + * Compare the loaded value with the value of register _xs2_ + * If equal, write the value of register _xs2+1_ to the address in _xs1_ + + +Decode Variables:: +[width="100%", cols="1,2", options="header"] +|=== +|Variable Name |Location +|xs2 |$encoding[24:20] +|xs1 |$encoding[19:15] +|xd |$encoding[11:7] +|=== + +Included in:: +[options="autowrap,autowidth"] +|=== +| Extension | Version + +| *Zacas* | ~> 1.0.0 + +|=== + + +[#udb:doc:inst:amocas_d_rl] +== amocas.d.rl + +Synopsis:: +Atomic compare-and-swap doubleword (release) + +Assembly:: +amocas.d.rl xd, xs2, (xs1) + +Encoding:: +[wavedrom, ,svg,subs='attributes',width="100%"] +.... +{"reg":[{"bits":7,"name": 0x2f,"type":2},{"bits":5,"name": "xd","type":4},{"bits":3,"name": 0x3,"type":2},{"bits":5,"name": "xs1","type":4},{"bits":5,"name": "xs2","type":4},{"bits":7,"name": 0x15,"type":2}]} +.... + +Description:: +Atomically with release ordering: + + * Load the doubleword at address _xs1_ + * Write the loaded value into _xd_ + * Compare the loaded value with the value of register _xs2_ + * If equal, write the value of register _xs2+1_ to the address in _xs1_ + + +Decode Variables:: +[width="100%", cols="1,2", options="header"] +|=== +|Variable Name |Location +|xs2 |$encoding[24:20] +|xs1 |$encoding[19:15] +|xd |$encoding[11:7] +|=== + +Included in:: +[options="autowrap,autowidth"] +|=== +| Extension | Version + +| *Zacas* | ~> 1.0.0 + +|=== + + +[#udb:doc:inst:amocas_h] +== amocas.h + +Synopsis:: +Atomic compare-and-swap halfword + +Assembly:: +amocas.h xd, xs2, (xs1) + +Encoding:: +[wavedrom, ,svg,subs='attributes',width="100%"] +.... +{"reg":[{"bits":7,"name": 0x2f,"type":2},{"bits":5,"name": "xd","type":4},{"bits":3,"name": 0x1,"type":2},{"bits":5,"name": "xs1","type":4},{"bits":5,"name": "xs2","type":4},{"bits":7,"name": 0x14,"type":2}]} +.... + +Description:: +Atomically: + + * Load the halfword at address _xs1_ + * Write the sign-extended value into _xd_ + * Compare the loaded value with the least-significant halfword of register _xs2_ + * If equal, write the least-significant halfword of register _xs2+1_ to the address in _xs1_ + + +Decode Variables:: +[width="100%", cols="1,2", options="header"] +|=== +|Variable Name |Location +|xs2 |$encoding[24:20] +|xs1 |$encoding[19:15] +|xd |$encoding[11:7] +|=== + +Included in:: +[options="autowrap,autowidth"] +|=== +| Extension | Version + +| *Zabha* | ~> 1.0.0 + +|=== + + +[#udb:doc:inst:amocas_h_aq] +== amocas.h.aq + +Synopsis:: +Atomic compare-and-swap halfword (acquire) + +Assembly:: +amocas.h.aq xd, xs2, (xs1) + +Encoding:: +[wavedrom, ,svg,subs='attributes',width="100%"] +.... +{"reg":[{"bits":7,"name": 0x2f,"type":2},{"bits":5,"name": "xd","type":4},{"bits":3,"name": 0x1,"type":2},{"bits":5,"name": "xs1","type":4},{"bits":5,"name": "xs2","type":4},{"bits":7,"name": 0x16,"type":2}]} +.... + +Description:: +Atomically with acquire ordering: + + * Load the halfword at address _xs1_ + * Write the sign-extended value into _xd_ + * Compare the loaded value with the least-significant halfword of register _xs2_ + * If equal, write the least-significant halfword of register _xs2+1_ to the address in _xs1_ + + +Decode Variables:: +[width="100%", cols="1,2", options="header"] +|=== +|Variable Name |Location +|xs2 |$encoding[24:20] +|xs1 |$encoding[19:15] +|xd |$encoding[11:7] +|=== + +Included in:: +[options="autowrap,autowidth"] +|=== +| Extension | Version + +| *Zabha* | ~> 1.0.0 + +|=== + + +[#udb:doc:inst:amocas_h_aqrl] +== amocas.h.aqrl + +Synopsis:: +Atomic compare-and-swap halfword (acquire-release) + +Assembly:: +amocas.h.aqrl xd, xs2, (xs1) + +Encoding:: +[wavedrom, ,svg,subs='attributes',width="100%"] +.... +{"reg":[{"bits":7,"name": 0x2f,"type":2},{"bits":5,"name": "xd","type":4},{"bits":3,"name": 0x1,"type":2},{"bits":5,"name": "xs1","type":4},{"bits":5,"name": "xs2","type":4},{"bits":7,"name": 0x17,"type":2}]} +.... + +Description:: +Atomically with acquire and release ordering: + + * Load the halfword at address _xs1_ + * Write the sign-extended value into _xd_ + * Compare the loaded value with the least-significant halfword of register _xs2_ + * If equal, write the least-significant halfword of register _xs2+1_ to the address in _xs1_ + + +Decode Variables:: +[width="100%", cols="1,2", options="header"] +|=== +|Variable Name |Location +|xs2 |$encoding[24:20] +|xs1 |$encoding[19:15] +|xd |$encoding[11:7] +|=== + +Included in:: +[options="autowrap,autowidth"] +|=== +| Extension | Version + +| *Zabha* | ~> 1.0.0 + +|=== + + +[#udb:doc:inst:amocas_h_rl] +== amocas.h.rl + +Synopsis:: +Atomic compare-and-swap halfword (release) + +Assembly:: +amocas.h.rl xd, xs2, (xs1) + +Encoding:: +[wavedrom, ,svg,subs='attributes',width="100%"] +.... +{"reg":[{"bits":7,"name": 0x2f,"type":2},{"bits":5,"name": "xd","type":4},{"bits":3,"name": 0x1,"type":2},{"bits":5,"name": "xs1","type":4},{"bits":5,"name": "xs2","type":4},{"bits":7,"name": 0x15,"type":2}]} +.... + +Description:: +Atomically with release ordering: + + * Load the halfword at address _xs1_ + * Write the sign-extended value into _xd_ + * Compare the loaded value with the least-significant halfword of register _xs2_ + * If equal, write the least-significant halfword of register _xs2+1_ to the address in _xs1_ + + +Decode Variables:: +[width="100%", cols="1,2", options="header"] +|=== +|Variable Name |Location +|xs2 |$encoding[24:20] +|xs1 |$encoding[19:15] +|xd |$encoding[11:7] +|=== + +Included in:: +[options="autowrap,autowidth"] +|=== +| Extension | Version + +| *Zabha* | ~> 1.0.0 + +|=== + + +[#udb:doc:inst:amocas_q] +== amocas.q + +Synopsis:: +Atomic compare-and-swap quadword + +Assembly:: +amocas.q xd, xs2, (xs1) + +Encoding:: +[wavedrom, ,svg,subs='attributes',width="100%"] +.... +{"reg":[{"bits":7,"name": 0x2f,"type":2},{"bits":5,"name": "xd","type":4},{"bits":3,"name": 0x4,"type":2},{"bits":5,"name": "xs1","type":4},{"bits":5,"name": "xs2","type":4},{"bits":7,"name": 0x14,"type":2}]} +.... + +Description:: +Atomically: + + * Load the quadword at address _xs1_ + * Write the loaded value into _xd_ + * Compare the loaded value with the value of register _xs2_ + * If equal, write the value of register _xs2+1_ to the address in _xs1_ + + +Decode Variables:: +[width="100%", cols="1,2", options="header"] +|=== +|Variable Name |Location +|xs2 |$encoding[24:20] +|xs1 |$encoding[19:15] +|xd |$encoding[11:7] +|=== + +Included in:: +[options="autowrap,autowidth"] +|=== +| Extension | Version + +| *Zacas* | ~> 1.0.0 + +|=== + + +[#udb:doc:inst:amocas_q_aq] +== amocas.q.aq + +Synopsis:: +Atomic compare-and-swap quadword (acquire) + +Assembly:: +amocas.q.aq xd, xs2, (xs1) + +Encoding:: +[wavedrom, ,svg,subs='attributes',width="100%"] +.... +{"reg":[{"bits":7,"name": 0x2f,"type":2},{"bits":5,"name": "xd","type":4},{"bits":3,"name": 0x4,"type":2},{"bits":5,"name": "xs1","type":4},{"bits":5,"name": "xs2","type":4},{"bits":7,"name": 0x16,"type":2}]} +.... + +Description:: +Atomically with acquire ordering: + + * Load the quadword at address _xs1_ + * Write the loaded value into _xd_ + * Compare the loaded value with the value of register _xs2_ + * If equal, write the value of register _xs2+1_ to the address in _xs1_ + + +Decode Variables:: +[width="100%", cols="1,2", options="header"] +|=== +|Variable Name |Location +|xs2 |$encoding[24:20] +|xs1 |$encoding[19:15] +|xd |$encoding[11:7] +|=== + +Included in:: +[options="autowrap,autowidth"] +|=== +| Extension | Version + +| *Zacas* | ~> 1.0.0 + +|=== + + +[#udb:doc:inst:amocas_q_aqrl] +== amocas.q.aqrl + +Synopsis:: +Atomic compare-and-swap quadword (acquire-release) + +Assembly:: +amocas.q.aqrl xd, xs2, (xs1) + +Encoding:: +[wavedrom, ,svg,subs='attributes',width="100%"] +.... +{"reg":[{"bits":7,"name": 0x2f,"type":2},{"bits":5,"name": "xd","type":4},{"bits":3,"name": 0x4,"type":2},{"bits":5,"name": "xs1","type":4},{"bits":5,"name": "xs2","type":4},{"bits":7,"name": 0x17,"type":2}]} +.... + +Description:: +Atomically with acquire and release ordering: + + * Load the quadword at address _xs1_ + * Write the loaded value into _xd_ + * Compare the loaded value with the value of register _xs2_ + * If equal, write the value of register _xs2+1_ to the address in _xs1_ + + +Decode Variables:: +[width="100%", cols="1,2", options="header"] +|=== +|Variable Name |Location +|xs2 |$encoding[24:20] +|xs1 |$encoding[19:15] +|xd |$encoding[11:7] +|=== + +Included in:: +[options="autowrap,autowidth"] +|=== +| Extension | Version + +| *Zacas* | ~> 1.0.0 + +|=== + + +[#udb:doc:inst:amocas_q_rl] +== amocas.q.rl + +Synopsis:: +Atomic compare-and-swap quadword (release) + +Assembly:: +amocas.q.rl xd, xs2, (xs1) + +Encoding:: +[wavedrom, ,svg,subs='attributes',width="100%"] +.... +{"reg":[{"bits":7,"name": 0x2f,"type":2},{"bits":5,"name": "xd","type":4},{"bits":3,"name": 0x4,"type":2},{"bits":5,"name": "xs1","type":4},{"bits":5,"name": "xs2","type":4},{"bits":7,"name": 0x15,"type":2}]} +.... + +Description:: +Atomically with release ordering: + + * Load the quadword at address _xs1_ + * Write the loaded value into _xd_ + * Compare the loaded value with the value of register _xs2_ + * If equal, write the value of register _xs2+1_ to the address in _xs1_ + + +Decode Variables:: +[width="100%", cols="1,2", options="header"] +|=== +|Variable Name |Location +|xs2 |$encoding[24:20] +|xs1 |$encoding[19:15] +|xd |$encoding[11:7] +|=== + +Included in:: +[options="autowrap,autowidth"] +|=== +| Extension | Version + +| *Zacas* | ~> 1.0.0 + +|=== + + +[#udb:doc:inst:amocas_w] +== amocas.w + +Synopsis:: +Atomic compare-and-swap word + +Assembly:: +amocas.w xd, xs2, (xs1) + +Encoding:: +[wavedrom, ,svg,subs='attributes',width="100%"] +.... +{"reg":[{"bits":7,"name": 0x2f,"type":2},{"bits":5,"name": "xd","type":4},{"bits":3,"name": 0x2,"type":2},{"bits":5,"name": "xs1","type":4},{"bits":5,"name": "xs2","type":4},{"bits":7,"name": 0x14,"type":2}]} +.... + +Description:: +Atomically: + + * Load the word at address _xs1_ + * Write the sign-extended value into _xd_ + * Compare the loaded value with the least-significant word of register _xs2_ + * If equal, write the least-significant word of register _xs2+1_ to the address in _xs1_ + + +Decode Variables:: +[width="100%", cols="1,2", options="header"] +|=== +|Variable Name |Location +|xs2 |$encoding[24:20] +|xs1 |$encoding[19:15] +|xd |$encoding[11:7] +|=== + +Included in:: +[options="autowrap,autowidth"] +|=== +| Extension | Version + +| *Zacas* | ~> 1.0.0 + +|=== + + +[#udb:doc:inst:amocas_w_aq] +== amocas.w.aq + +Synopsis:: +Atomic compare-and-swap word (acquire) + +Assembly:: +amocas.w.aq xd, xs2, (xs1) + +Encoding:: +[wavedrom, ,svg,subs='attributes',width="100%"] +.... +{"reg":[{"bits":7,"name": 0x2f,"type":2},{"bits":5,"name": "xd","type":4},{"bits":3,"name": 0x2,"type":2},{"bits":5,"name": "xs1","type":4},{"bits":5,"name": "xs2","type":4},{"bits":7,"name": 0x16,"type":2}]} +.... + +Description:: +Atomically with acquire ordering: + + * Load the word at address _xs1_ + * Write the sign-extended value into _xd_ + * Compare the loaded value with the least-significant word of register _xs2_ + * If equal, write the least-significant word of register _xs2+1_ to the address in _xs1_ + + +Decode Variables:: +[width="100%", cols="1,2", options="header"] +|=== +|Variable Name |Location +|xs2 |$encoding[24:20] +|xs1 |$encoding[19:15] +|xd |$encoding[11:7] +|=== + +Included in:: +[options="autowrap,autowidth"] +|=== +| Extension | Version + +| *Zacas* | ~> 1.0.0 + +|=== + + +[#udb:doc:inst:amocas_w_aqrl] +== amocas.w.aqrl + +Synopsis:: +Atomic compare-and-swap word (acquire-release) + +Assembly:: +amocas.w.aqrl xd, xs2, (xs1) + +Encoding:: +[wavedrom, ,svg,subs='attributes',width="100%"] +.... +{"reg":[{"bits":7,"name": 0x2f,"type":2},{"bits":5,"name": "xd","type":4},{"bits":3,"name": 0x2,"type":2},{"bits":5,"name": "xs1","type":4},{"bits":5,"name": "xs2","type":4},{"bits":7,"name": 0x17,"type":2}]} +.... + +Description:: +Atomically with acquire and release ordering: + + * Load the word at address _xs1_ + * Write the sign-extended value into _xd_ + * Compare the loaded value with the least-significant word of register _xs2_ + * If equal, write the least-significant word of register _xs2+1_ to the address in _xs1_ + + +Decode Variables:: +[width="100%", cols="1,2", options="header"] +|=== +|Variable Name |Location +|xs2 |$encoding[24:20] +|xs1 |$encoding[19:15] +|xd |$encoding[11:7] +|=== + +Included in:: +[options="autowrap,autowidth"] +|=== +| Extension | Version + +| *Zacas* | ~> 1.0.0 + +|=== + + +[#udb:doc:inst:amocas_w_rl] +== amocas.w.rl + +Synopsis:: +Atomic compare-and-swap word (release) + +Assembly:: +amocas.w.rl xd, xs2, (xs1) + +Encoding:: +[wavedrom, ,svg,subs='attributes',width="100%"] +.... +{"reg":[{"bits":7,"name": 0x2f,"type":2},{"bits":5,"name": "xd","type":4},{"bits":3,"name": 0x2,"type":2},{"bits":5,"name": "xs1","type":4},{"bits":5,"name": "xs2","type":4},{"bits":7,"name": 0x15,"type":2}]} +.... + +Description:: +Atomically with release ordering: + + * Load the word at address _xs1_ + * Write the sign-extended value into _xd_ + * Compare the loaded value with the least-significant word of register _xs2_ + * If equal, write the least-significant word of register _xs2+1_ to the address in _xs1_ + + +Decode Variables:: +[width="100%", cols="1,2", options="header"] +|=== +|Variable Name |Location +|xs2 |$encoding[24:20] +|xs1 |$encoding[19:15] +|xd |$encoding[11:7] +|=== + +Included in:: +[options="autowrap,autowidth"] +|=== +| Extension | Version + +| *Zacas* | ~> 1.0.0 + +|=== + + +[#udb:doc:inst:amomax_b] +== amomax.b + +Synopsis:: +Atomic MAX byte + +Assembly:: +amomax.b xd, xs2, (xs1) + +Encoding:: +[wavedrom, ,svg,subs='attributes',width="100%"] +.... +{"reg":[{"bits":7,"name": 0x2f,"type":2},{"bits":5,"name": "xd","type":4},{"bits":3,"name": 0x0,"type":2},{"bits":5,"name": "xs1","type":4},{"bits":5,"name": "xs2","type":4},{"bits":7,"name": 0x50,"type":2}]} +.... + +Description:: +Atomically: + + * Load the byte at address _xs1_ + * Write the sign-extended value into _xd_ + * Signed compare the least-significant byte of register _xs2_ to the loaded value, and select the maximum value + * Write the maximum to the address in _xs1_ + + +Decode Variables:: +[width="100%", cols="1,2", options="header"] +|=== +|Variable Name |Location +|xs2 |$encoding[24:20] +|xs1 |$encoding[19:15] +|xd |$encoding[11:7] +|=== + +Included in:: +[options="autowrap,autowidth"] +|=== +| Extension | Version + +| *Zabha* | ~> 1.0.0 + +|=== + + +[#udb:doc:inst:amomax_b_aq] +== amomax.b.aq + +Synopsis:: +Atomic MAX byte (acquire) + +Assembly:: +amomax.b.aq xd, xs2, (xs1) + +Encoding:: +[wavedrom, ,svg,subs='attributes',width="100%"] +.... +{"reg":[{"bits":7,"name": 0x2f,"type":2},{"bits":5,"name": "xd","type":4},{"bits":3,"name": 0x0,"type":2},{"bits":5,"name": "xs1","type":4},{"bits":5,"name": "xs2","type":4},{"bits":7,"name": 0x52,"type":2}]} +.... + +Description:: +Atomically with acquire ordering: + + * Load the byte at address _xs1_ + * Write the sign-extended value into _xd_ + * Signed compare the least-significant byte of register _xs2_ to the loaded value, and select the maximum value + * Write the maximum to the address in _xs1_ + + +Decode Variables:: +[width="100%", cols="1,2", options="header"] +|=== +|Variable Name |Location +|xs2 |$encoding[24:20] +|xs1 |$encoding[19:15] +|xd |$encoding[11:7] +|=== + +Included in:: +[options="autowrap,autowidth"] +|=== +| Extension | Version + +| *Zabha* | ~> 1.0.0 + +|=== + + +[#udb:doc:inst:amomax_b_aqrl] +== amomax.b.aqrl + +Synopsis:: +Atomic MAX byte (acquire-release) + +Assembly:: +amomax.b.aqrl xd, xs2, (xs1) + +Encoding:: +[wavedrom, ,svg,subs='attributes',width="100%"] +.... +{"reg":[{"bits":7,"name": 0x2f,"type":2},{"bits":5,"name": "xd","type":4},{"bits":3,"name": 0x0,"type":2},{"bits":5,"name": "xs1","type":4},{"bits":5,"name": "xs2","type":4},{"bits":7,"name": 0x53,"type":2}]} +.... + +Description:: +Atomically with acquire and release ordering: + + * Load the byte at address _xs1_ + * Write the sign-extended value into _xd_ + * Signed compare the least-significant byte of register _xs2_ to the loaded value, and select the maximum value + * Write the maximum to the address in _xs1_ + + +Decode Variables:: +[width="100%", cols="1,2", options="header"] +|=== +|Variable Name |Location +|xs2 |$encoding[24:20] +|xs1 |$encoding[19:15] +|xd |$encoding[11:7] +|=== + +Included in:: +[options="autowrap,autowidth"] +|=== +| Extension | Version + +| *Zabha* | ~> 1.0.0 + +|=== + + +[#udb:doc:inst:amomax_b_rl] +== amomax.b.rl + +Synopsis:: +Atomic MAX byte (release) + +Assembly:: +amomax.b.rl xd, xs2, (xs1) + +Encoding:: +[wavedrom, ,svg,subs='attributes',width="100%"] +.... +{"reg":[{"bits":7,"name": 0x2f,"type":2},{"bits":5,"name": "xd","type":4},{"bits":3,"name": 0x0,"type":2},{"bits":5,"name": "xs1","type":4},{"bits":5,"name": "xs2","type":4},{"bits":7,"name": 0x51,"type":2}]} +.... + +Description:: +Atomically with release ordering: + + * Load the byte at address _xs1_ + * Write the sign-extended value into _xd_ + * Signed compare the least-significant byte of register _xs2_ to the loaded value, and select the maximum value + * Write the maximum to the address in _xs1_ + + +Decode Variables:: +[width="100%", cols="1,2", options="header"] +|=== +|Variable Name |Location +|xs2 |$encoding[24:20] +|xs1 |$encoding[19:15] +|xd |$encoding[11:7] +|=== + +Included in:: +[options="autowrap,autowidth"] +|=== +| Extension | Version + +| *Zabha* | ~> 1.0.0 + +|=== + + +[#udb:doc:inst:amomax_d] +== amomax.d + +Synopsis:: +Atomic MAX doubleword + +Assembly:: +amomax.d xd, xs2, (xs1) + +Encoding:: +[wavedrom, ,svg,subs='attributes',width="100%"] +.... +{"reg":[{"bits":7,"name": 0x2f,"type":2},{"bits":5,"name": "xd","type":4},{"bits":3,"name": 0x3,"type":2},{"bits":5,"name": "xs1","type":4},{"bits":5,"name": "xs2","type":4},{"bits":7,"name": 0x50,"type":2}]} +.... + +Description:: +Atomically: + + * Load the doubleword at address _xs1_ + * Write the loaded value into _xd_ + * Signed compare the value of register _xs2_ to the loaded value, and select the maximum value + * Write the maximum to the address in _xs1_ + + +Decode Variables:: +[width="100%", cols="1,2", options="header"] +|=== +|Variable Name |Location +|xs2 |$encoding[24:20] +|xs1 |$encoding[19:15] +|xd |$encoding[11:7] +|=== + +Included in:: +[options="autowrap,autowidth"] +|=== +| Extension | Version + +| *Zaamo* | ~> 1.0.0 + +|=== + + +[#udb:doc:inst:amomax_d_aq] +== amomax.d.aq + +Synopsis:: +Atomic MAX doubleword (acquire) + +Assembly:: +amomax.d.aq xd, xs2, (xs1) + +Encoding:: +[wavedrom, ,svg,subs='attributes',width="100%"] +.... +{"reg":[{"bits":7,"name": 0x2f,"type":2},{"bits":5,"name": "xd","type":4},{"bits":3,"name": 0x3,"type":2},{"bits":5,"name": "xs1","type":4},{"bits":5,"name": "xs2","type":4},{"bits":7,"name": 0x52,"type":2}]} +.... + +Description:: +Atomically with acquire ordering: + + * Load the doubleword at address _xs1_ + * Write the loaded value into _xd_ + * Signed compare the value of register _xs2_ to the loaded value, and select the maximum value + * Write the maximum to the address in _xs1_ + + +Decode Variables:: +[width="100%", cols="1,2", options="header"] +|=== +|Variable Name |Location +|xs2 |$encoding[24:20] +|xs1 |$encoding[19:15] +|xd |$encoding[11:7] +|=== + +Included in:: +[options="autowrap,autowidth"] +|=== +| Extension | Version + +| *Zaamo* | ~> 1.0.0 + +|=== + + +[#udb:doc:inst:amomax_d_aqrl] +== amomax.d.aqrl + +Synopsis:: +Atomic MAX doubleword (acquire-release) + +Assembly:: +amomax.d.aqrl xd, xs2, (xs1) + +Encoding:: +[wavedrom, ,svg,subs='attributes',width="100%"] +.... +{"reg":[{"bits":7,"name": 0x2f,"type":2},{"bits":5,"name": "xd","type":4},{"bits":3,"name": 0x3,"type":2},{"bits":5,"name": "xs1","type":4},{"bits":5,"name": "xs2","type":4},{"bits":7,"name": 0x53,"type":2}]} +.... + +Description:: +Atomically with acquire and release ordering: + + * Load the doubleword at address _xs1_ + * Write the loaded value into _xd_ + * Signed compare the value of register _xs2_ to the loaded value, and select the maximum value + * Write the maximum to the address in _xs1_ + + +Decode Variables:: +[width="100%", cols="1,2", options="header"] +|=== +|Variable Name |Location +|xs2 |$encoding[24:20] +|xs1 |$encoding[19:15] +|xd |$encoding[11:7] +|=== + +Included in:: +[options="autowrap,autowidth"] +|=== +| Extension | Version + +| *Zaamo* | ~> 1.0.0 + +|=== + + +[#udb:doc:inst:amomax_d_rl] +== amomax.d.rl + +Synopsis:: +Atomic MAX doubleword (release) + +Assembly:: +amomax.d.rl xd, xs2, (xs1) + +Encoding:: +[wavedrom, ,svg,subs='attributes',width="100%"] +.... +{"reg":[{"bits":7,"name": 0x2f,"type":2},{"bits":5,"name": "xd","type":4},{"bits":3,"name": 0x3,"type":2},{"bits":5,"name": "xs1","type":4},{"bits":5,"name": "xs2","type":4},{"bits":7,"name": 0x51,"type":2}]} +.... + +Description:: +Atomically with release ordering: + + * Load the doubleword at address _xs1_ + * Write the loaded value into _xd_ + * Signed compare the value of register _xs2_ to the loaded value, and select the maximum value + * Write the maximum to the address in _xs1_ + + +Decode Variables:: +[width="100%", cols="1,2", options="header"] +|=== +|Variable Name |Location +|xs2 |$encoding[24:20] +|xs1 |$encoding[19:15] +|xd |$encoding[11:7] +|=== + +Included in:: +[options="autowrap,autowidth"] +|=== +| Extension | Version + +| *Zaamo* | ~> 1.0.0 + +|=== + + +[#udb:doc:inst:amomax_h] +== amomax.h + +Synopsis:: +Atomic MAX halfword + +Assembly:: +amomax.h xd, xs2, (xs1) + +Encoding:: +[wavedrom, ,svg,subs='attributes',width="100%"] +.... +{"reg":[{"bits":7,"name": 0x2f,"type":2},{"bits":5,"name": "xd","type":4},{"bits":3,"name": 0x1,"type":2},{"bits":5,"name": "xs1","type":4},{"bits":5,"name": "xs2","type":4},{"bits":7,"name": 0x50,"type":2}]} +.... + +Description:: +Atomically: + + * Load the halfword at address _xs1_ + * Write the sign-extended value into _xd_ + * Signed compare the least-significant halfword of register _xs2_ to the loaded value, and select the maximum value + * Write the maximum to the address in _xs1_ + + +Decode Variables:: +[width="100%", cols="1,2", options="header"] +|=== +|Variable Name |Location +|xs2 |$encoding[24:20] +|xs1 |$encoding[19:15] +|xd |$encoding[11:7] +|=== + +Included in:: +[options="autowrap,autowidth"] +|=== +| Extension | Version + +| *Zabha* | ~> 1.0.0 + +|=== + + +[#udb:doc:inst:amomax_h_aq] +== amomax.h.aq + +Synopsis:: +Atomic MAX halfword (acquire) + +Assembly:: +amomax.h.aq xd, xs2, (xs1) + +Encoding:: +[wavedrom, ,svg,subs='attributes',width="100%"] +.... +{"reg":[{"bits":7,"name": 0x2f,"type":2},{"bits":5,"name": "xd","type":4},{"bits":3,"name": 0x1,"type":2},{"bits":5,"name": "xs1","type":4},{"bits":5,"name": "xs2","type":4},{"bits":7,"name": 0x52,"type":2}]} +.... + +Description:: +Atomically with acquire ordering: + + * Load the halfword at address _xs1_ + * Write the sign-extended value into _xd_ + * Signed compare the least-significant halfword of register _xs2_ to the loaded value, and select the maximum value + * Write the maximum to the address in _xs1_ + + +Decode Variables:: +[width="100%", cols="1,2", options="header"] +|=== +|Variable Name |Location +|xs2 |$encoding[24:20] +|xs1 |$encoding[19:15] +|xd |$encoding[11:7] +|=== + +Included in:: +[options="autowrap,autowidth"] +|=== +| Extension | Version + +| *Zabha* | ~> 1.0.0 + +|=== + + +[#udb:doc:inst:amomax_h_aqrl] +== amomax.h.aqrl + +Synopsis:: +Atomic MAX halfword (acquire-release) + +Assembly:: +amomax.h.aqrl xd, xs2, (xs1) + +Encoding:: +[wavedrom, ,svg,subs='attributes',width="100%"] +.... +{"reg":[{"bits":7,"name": 0x2f,"type":2},{"bits":5,"name": "xd","type":4},{"bits":3,"name": 0x1,"type":2},{"bits":5,"name": "xs1","type":4},{"bits":5,"name": "xs2","type":4},{"bits":7,"name": 0x53,"type":2}]} +.... + +Description:: +Atomically with acquire and release ordering: + + * Load the halfword at address _xs1_ + * Write the sign-extended value into _xd_ + * Signed compare the least-significant halfword of register _xs2_ to the loaded value, and select the maximum value + * Write the maximum to the address in _xs1_ + + +Decode Variables:: +[width="100%", cols="1,2", options="header"] +|=== +|Variable Name |Location +|xs2 |$encoding[24:20] +|xs1 |$encoding[19:15] +|xd |$encoding[11:7] +|=== + +Included in:: +[options="autowrap,autowidth"] +|=== +| Extension | Version + +| *Zabha* | ~> 1.0.0 + +|=== + + +[#udb:doc:inst:amomax_h_rl] +== amomax.h.rl + +Synopsis:: +Atomic MAX halfword (release) + +Assembly:: +amomax.h.rl xd, xs2, (xs1) + +Encoding:: +[wavedrom, ,svg,subs='attributes',width="100%"] +.... +{"reg":[{"bits":7,"name": 0x2f,"type":2},{"bits":5,"name": "xd","type":4},{"bits":3,"name": 0x1,"type":2},{"bits":5,"name": "xs1","type":4},{"bits":5,"name": "xs2","type":4},{"bits":7,"name": 0x51,"type":2}]} +.... + +Description:: +Atomically with release ordering: + + * Load the halfword at address _xs1_ + * Write the sign-extended value into _xd_ + * Signed compare the least-significant halfword of register _xs2_ to the loaded value, and select the maximum value + * Write the maximum to the address in _xs1_ + + +Decode Variables:: +[width="100%", cols="1,2", options="header"] +|=== +|Variable Name |Location +|xs2 |$encoding[24:20] +|xs1 |$encoding[19:15] +|xd |$encoding[11:7] +|=== + +Included in:: +[options="autowrap,autowidth"] +|=== +| Extension | Version + +| *Zabha* | ~> 1.0.0 + +|=== + + +[#udb:doc:inst:amomax_w] +== amomax.w + +Synopsis:: +Atomic MAX word + +Assembly:: +amomax.w xd, xs2, (xs1) + +Encoding:: +[wavedrom, ,svg,subs='attributes',width="100%"] +.... +{"reg":[{"bits":7,"name": 0x2f,"type":2},{"bits":5,"name": "xd","type":4},{"bits":3,"name": 0x2,"type":2},{"bits":5,"name": "xs1","type":4},{"bits":5,"name": "xs2","type":4},{"bits":7,"name": 0x50,"type":2}]} +.... + +Description:: +Atomically: + + * Load the word at address _xs1_ + * Write the sign-extended value into _xd_ + * Signed compare the least-significant word of register _xs2_ to the loaded value, and select the maximum value + * Write the maximum to the address in _xs1_ + + +Decode Variables:: +[width="100%", cols="1,2", options="header"] +|=== +|Variable Name |Location +|xs2 |$encoding[24:20] +|xs1 |$encoding[19:15] +|xd |$encoding[11:7] +|=== + +Included in:: +[options="autowrap,autowidth"] +|=== +| Extension | Version + +| *Zaamo* | ~> 1.0.0 + +|=== + + +[#udb:doc:inst:amomax_w_aq] +== amomax.w.aq + +Synopsis:: +Atomic MAX word (acquire) + +Assembly:: +amomax.w.aq xd, xs2, (xs1) + +Encoding:: +[wavedrom, ,svg,subs='attributes',width="100%"] +.... +{"reg":[{"bits":7,"name": 0x2f,"type":2},{"bits":5,"name": "xd","type":4},{"bits":3,"name": 0x2,"type":2},{"bits":5,"name": "xs1","type":4},{"bits":5,"name": "xs2","type":4},{"bits":7,"name": 0x52,"type":2}]} +.... + +Description:: +Atomically with acquire ordering: + + * Load the word at address _xs1_ + * Write the sign-extended value into _xd_ + * Signed compare the least-significant word of register _xs2_ to the loaded value, and select the maximum value + * Write the maximum to the address in _xs1_ + + +Decode Variables:: +[width="100%", cols="1,2", options="header"] +|=== +|Variable Name |Location +|xs2 |$encoding[24:20] +|xs1 |$encoding[19:15] +|xd |$encoding[11:7] +|=== + +Included in:: +[options="autowrap,autowidth"] +|=== +| Extension | Version + +| *Zaamo* | ~> 1.0.0 + +|=== + + +[#udb:doc:inst:amomax_w_aqrl] +== amomax.w.aqrl + +Synopsis:: +Atomic MAX word (acquire-release) + +Assembly:: +amomax.w.aqrl xd, xs2, (xs1) + +Encoding:: +[wavedrom, ,svg,subs='attributes',width="100%"] +.... +{"reg":[{"bits":7,"name": 0x2f,"type":2},{"bits":5,"name": "xd","type":4},{"bits":3,"name": 0x2,"type":2},{"bits":5,"name": "xs1","type":4},{"bits":5,"name": "xs2","type":4},{"bits":7,"name": 0x53,"type":2}]} +.... + +Description:: +Atomically with acquire and release ordering: + + * Load the word at address _xs1_ + * Write the sign-extended value into _xd_ + * Signed compare the least-significant word of register _xs2_ to the loaded value, and select the maximum value + * Write the maximum to the address in _xs1_ + + +Decode Variables:: +[width="100%", cols="1,2", options="header"] +|=== +|Variable Name |Location +|xs2 |$encoding[24:20] +|xs1 |$encoding[19:15] +|xd |$encoding[11:7] +|=== + +Included in:: +[options="autowrap,autowidth"] +|=== +| Extension | Version + +| *Zaamo* | ~> 1.0.0 + +|=== + + +[#udb:doc:inst:amomax_w_rl] +== amomax.w.rl + +Synopsis:: +Atomic MAX word (release) + +Assembly:: +amomax.w.rl xd, xs2, (xs1) + +Encoding:: +[wavedrom, ,svg,subs='attributes',width="100%"] +.... +{"reg":[{"bits":7,"name": 0x2f,"type":2},{"bits":5,"name": "xd","type":4},{"bits":3,"name": 0x2,"type":2},{"bits":5,"name": "xs1","type":4},{"bits":5,"name": "xs2","type":4},{"bits":7,"name": 0x51,"type":2}]} +.... + +Description:: +Atomically with release ordering: + + * Load the word at address _xs1_ + * Write the sign-extended value into _xd_ + * Signed compare the least-significant word of register _xs2_ to the loaded value, and select the maximum value + * Write the maximum to the address in _xs1_ + + +Decode Variables:: +[width="100%", cols="1,2", options="header"] +|=== +|Variable Name |Location +|xs2 |$encoding[24:20] +|xs1 |$encoding[19:15] +|xd |$encoding[11:7] +|=== + +Included in:: +[options="autowrap,autowidth"] +|=== +| Extension | Version + +| *Zaamo* | ~> 1.0.0 + +|=== + + +[#udb:doc:inst:amomaxu_b] +== amomaxu.b + +Synopsis:: +Atomic MAX unsigned byte + +Assembly:: +amomaxu.b xd, xs2, (xs1) + +Encoding:: +[wavedrom, ,svg,subs='attributes',width="100%"] +.... +{"reg":[{"bits":7,"name": 0x2f,"type":2},{"bits":5,"name": "xd","type":4},{"bits":3,"name": 0x0,"type":2},{"bits":5,"name": "xs1","type":4},{"bits":5,"name": "xs2","type":4},{"bits":7,"name": 0x70,"type":2}]} +.... + +Description:: +Atomically: + + * Load the byte at address _xs1_ + * Write the sign-extended value into _xd_ + * Unsigned compare the least-significant byte of register _xs2_ to the loaded value, and select the maximum value + * Write the maximum to the address in _xs1_ + + +Decode Variables:: +[width="100%", cols="1,2", options="header"] +|=== +|Variable Name |Location +|xs2 |$encoding[24:20] +|xs1 |$encoding[19:15] +|xd |$encoding[11:7] +|=== + +Included in:: +[options="autowrap,autowidth"] +|=== +| Extension | Version + +| *Zabha* | ~> 1.0.0 + +|=== + + +[#udb:doc:inst:amomaxu_b_aq] +== amomaxu.b.aq + +Synopsis:: +Atomic MAX unsigned byte (acquire) + +Assembly:: +amomaxu.b.aq xd, xs2, (xs1) + +Encoding:: +[wavedrom, ,svg,subs='attributes',width="100%"] +.... +{"reg":[{"bits":7,"name": 0x2f,"type":2},{"bits":5,"name": "xd","type":4},{"bits":3,"name": 0x0,"type":2},{"bits":5,"name": "xs1","type":4},{"bits":5,"name": "xs2","type":4},{"bits":7,"name": 0x72,"type":2}]} +.... + +Description:: +Atomically with acquire ordering: + + * Load the byte at address _xs1_ + * Write the sign-extended value into _xd_ + * Unsigned compare the least-significant byte of register _xs2_ to the loaded value, and select the maximum value + * Write the maximum to the address in _xs1_ + + +Decode Variables:: +[width="100%", cols="1,2", options="header"] +|=== +|Variable Name |Location +|xs2 |$encoding[24:20] +|xs1 |$encoding[19:15] +|xd |$encoding[11:7] +|=== + +Included in:: +[options="autowrap,autowidth"] +|=== +| Extension | Version + +| *Zabha* | ~> 1.0.0 + +|=== + + +[#udb:doc:inst:amomaxu_b_aqrl] +== amomaxu.b.aqrl + +Synopsis:: +Atomic MAX unsigned byte (acquire-release) + +Assembly:: +amomaxu.b.aqrl xd, xs2, (xs1) + +Encoding:: +[wavedrom, ,svg,subs='attributes',width="100%"] +.... +{"reg":[{"bits":7,"name": 0x2f,"type":2},{"bits":5,"name": "xd","type":4},{"bits":3,"name": 0x0,"type":2},{"bits":5,"name": "xs1","type":4},{"bits":5,"name": "xs2","type":4},{"bits":7,"name": 0x73,"type":2}]} +.... + +Description:: +Atomically with acquire and release ordering: + + * Load the byte at address _xs1_ + * Write the sign-extended value into _xd_ + * Unsigned compare the least-significant byte of register _xs2_ to the loaded value, and select the maximum value + * Write the maximum to the address in _xs1_ + + +Decode Variables:: +[width="100%", cols="1,2", options="header"] +|=== +|Variable Name |Location +|xs2 |$encoding[24:20] +|xs1 |$encoding[19:15] +|xd |$encoding[11:7] +|=== + +Included in:: +[options="autowrap,autowidth"] +|=== +| Extension | Version + +| *Zabha* | ~> 1.0.0 + +|=== + + +[#udb:doc:inst:amomaxu_b_rl] +== amomaxu.b.rl + +Synopsis:: +Atomic MAX unsigned byte (release) + +Assembly:: +amomaxu.b.rl xd, xs2, (xs1) + +Encoding:: +[wavedrom, ,svg,subs='attributes',width="100%"] +.... +{"reg":[{"bits":7,"name": 0x2f,"type":2},{"bits":5,"name": "xd","type":4},{"bits":3,"name": 0x0,"type":2},{"bits":5,"name": "xs1","type":4},{"bits":5,"name": "xs2","type":4},{"bits":7,"name": 0x71,"type":2}]} +.... + +Description:: +Atomically with release ordering: + + * Load the byte at address _xs1_ + * Write the sign-extended value into _xd_ + * Unsigned compare the least-significant byte of register _xs2_ to the loaded value, and select the maximum value + * Write the maximum to the address in _xs1_ + + +Decode Variables:: +[width="100%", cols="1,2", options="header"] +|=== +|Variable Name |Location +|xs2 |$encoding[24:20] +|xs1 |$encoding[19:15] +|xd |$encoding[11:7] +|=== + +Included in:: +[options="autowrap,autowidth"] +|=== +| Extension | Version + +| *Zabha* | ~> 1.0.0 + +|=== + + +[#udb:doc:inst:amomaxu_d] +== amomaxu.d + +Synopsis:: +Atomic MAX unsigned doubleword + +Assembly:: +amomaxu.d xd, xs2, (xs1) + +Encoding:: +[wavedrom, ,svg,subs='attributes',width="100%"] +.... +{"reg":[{"bits":7,"name": 0x2f,"type":2},{"bits":5,"name": "xd","type":4},{"bits":3,"name": 0x3,"type":2},{"bits":5,"name": "xs1","type":4},{"bits":5,"name": "xs2","type":4},{"bits":7,"name": 0x70,"type":2}]} +.... + +Description:: +Atomically: + + * Load the doubleword at address _xs1_ + * Write the loaded value into _xd_ + * Unsigned compare the value of register _xs2_ to the loaded value, and select the maximum value + * Write the maximum to the address in _xs1_ + + +Decode Variables:: +[width="100%", cols="1,2", options="header"] +|=== +|Variable Name |Location +|xs2 |$encoding[24:20] +|xs1 |$encoding[19:15] +|xd |$encoding[11:7] +|=== + +Included in:: +[options="autowrap,autowidth"] +|=== +| Extension | Version + +| *Zaamo* | ~> 1.0.0 + +|=== + + +[#udb:doc:inst:amomaxu_d_aq] +== amomaxu.d.aq + +Synopsis:: +Atomic MAX unsigned doubleword (acquire) + +Assembly:: +amomaxu.d.aq xd, xs2, (xs1) + +Encoding:: +[wavedrom, ,svg,subs='attributes',width="100%"] +.... +{"reg":[{"bits":7,"name": 0x2f,"type":2},{"bits":5,"name": "xd","type":4},{"bits":3,"name": 0x3,"type":2},{"bits":5,"name": "xs1","type":4},{"bits":5,"name": "xs2","type":4},{"bits":7,"name": 0x72,"type":2}]} +.... + +Description:: +Atomically with acquire ordering: + + * Load the doubleword at address _xs1_ + * Write the loaded value into _xd_ + * Unsigned compare the value of register _xs2_ to the loaded value, and select the maximum value + * Write the maximum to the address in _xs1_ + + +Decode Variables:: +[width="100%", cols="1,2", options="header"] +|=== +|Variable Name |Location +|xs2 |$encoding[24:20] +|xs1 |$encoding[19:15] +|xd |$encoding[11:7] +|=== + +Included in:: +[options="autowrap,autowidth"] +|=== +| Extension | Version + +| *Zaamo* | ~> 1.0.0 + +|=== + + +[#udb:doc:inst:amomaxu_d_aqrl] +== amomaxu.d.aqrl + +Synopsis:: +Atomic MAX unsigned doubleword (acquire-release) + +Assembly:: +amomaxu.d.aqrl xd, xs2, (xs1) + +Encoding:: +[wavedrom, ,svg,subs='attributes',width="100%"] +.... +{"reg":[{"bits":7,"name": 0x2f,"type":2},{"bits":5,"name": "xd","type":4},{"bits":3,"name": 0x3,"type":2},{"bits":5,"name": "xs1","type":4},{"bits":5,"name": "xs2","type":4},{"bits":7,"name": 0x73,"type":2}]} +.... + +Description:: +Atomically with acquire and release ordering: + + * Load the doubleword at address _xs1_ + * Write the loaded value into _xd_ + * Unsigned compare the value of register _xs2_ to the loaded value, and select the maximum value + * Write the maximum to the address in _xs1_ + + +Decode Variables:: +[width="100%", cols="1,2", options="header"] +|=== +|Variable Name |Location +|xs2 |$encoding[24:20] +|xs1 |$encoding[19:15] +|xd |$encoding[11:7] +|=== + +Included in:: +[options="autowrap,autowidth"] +|=== +| Extension | Version + +| *Zaamo* | ~> 1.0.0 + +|=== + + +[#udb:doc:inst:amomaxu_d_rl] +== amomaxu.d.rl + +Synopsis:: +Atomic MAX unsigned doubleword (release) + +Assembly:: +amomaxu.d.rl xd, xs2, (xs1) + +Encoding:: +[wavedrom, ,svg,subs='attributes',width="100%"] +.... +{"reg":[{"bits":7,"name": 0x2f,"type":2},{"bits":5,"name": "xd","type":4},{"bits":3,"name": 0x3,"type":2},{"bits":5,"name": "xs1","type":4},{"bits":5,"name": "xs2","type":4},{"bits":7,"name": 0x71,"type":2}]} +.... + +Description:: +Atomically with release ordering: + + * Load the doubleword at address _xs1_ + * Write the loaded value into _xd_ + * Unsigned compare the value of register _xs2_ to the loaded value, and select the maximum value + * Write the maximum to the address in _xs1_ + + +Decode Variables:: +[width="100%", cols="1,2", options="header"] +|=== +|Variable Name |Location +|xs2 |$encoding[24:20] +|xs1 |$encoding[19:15] +|xd |$encoding[11:7] +|=== + +Included in:: +[options="autowrap,autowidth"] +|=== +| Extension | Version + +| *Zaamo* | ~> 1.0.0 + +|=== + + +[#udb:doc:inst:amomaxu_h] +== amomaxu.h + +Synopsis:: +Atomic MAX unsigned halfword + +Assembly:: +amomaxu.h xd, xs2, (xs1) + +Encoding:: +[wavedrom, ,svg,subs='attributes',width="100%"] +.... +{"reg":[{"bits":7,"name": 0x2f,"type":2},{"bits":5,"name": "xd","type":4},{"bits":3,"name": 0x1,"type":2},{"bits":5,"name": "xs1","type":4},{"bits":5,"name": "xs2","type":4},{"bits":7,"name": 0x70,"type":2}]} +.... + +Description:: +Atomically: + + * Load the halfword at address _xs1_ + * Write the sign-extended value into _xd_ + * Unsigned compare the least-significant halfword of register _xs2_ to the loaded value, and select the maximum value + * Write the maximum to the address in _xs1_ + + +Decode Variables:: +[width="100%", cols="1,2", options="header"] +|=== +|Variable Name |Location +|xs2 |$encoding[24:20] +|xs1 |$encoding[19:15] +|xd |$encoding[11:7] +|=== + +Included in:: +[options="autowrap,autowidth"] +|=== +| Extension | Version + +| *Zabha* | ~> 1.0.0 + +|=== + + +[#udb:doc:inst:amomaxu_h_aq] +== amomaxu.h.aq + +Synopsis:: +Atomic MAX unsigned halfword (acquire) + +Assembly:: +amomaxu.h.aq xd, xs2, (xs1) + +Encoding:: +[wavedrom, ,svg,subs='attributes',width="100%"] +.... +{"reg":[{"bits":7,"name": 0x2f,"type":2},{"bits":5,"name": "xd","type":4},{"bits":3,"name": 0x1,"type":2},{"bits":5,"name": "xs1","type":4},{"bits":5,"name": "xs2","type":4},{"bits":7,"name": 0x72,"type":2}]} +.... + +Description:: +Atomically with acquire ordering: + + * Load the halfword at address _xs1_ + * Write the sign-extended value into _xd_ + * Unsigned compare the least-significant halfword of register _xs2_ to the loaded value, and select the maximum value + * Write the maximum to the address in _xs1_ + + +Decode Variables:: +[width="100%", cols="1,2", options="header"] +|=== +|Variable Name |Location +|xs2 |$encoding[24:20] +|xs1 |$encoding[19:15] +|xd |$encoding[11:7] +|=== + +Included in:: +[options="autowrap,autowidth"] +|=== +| Extension | Version + +| *Zabha* | ~> 1.0.0 + +|=== + + +[#udb:doc:inst:amomaxu_h_aqrl] +== amomaxu.h.aqrl + +Synopsis:: +Atomic MAX unsigned halfword (acquire-release) + +Assembly:: +amomaxu.h.aqrl xd, xs2, (xs1) + +Encoding:: +[wavedrom, ,svg,subs='attributes',width="100%"] +.... +{"reg":[{"bits":7,"name": 0x2f,"type":2},{"bits":5,"name": "xd","type":4},{"bits":3,"name": 0x1,"type":2},{"bits":5,"name": "xs1","type":4},{"bits":5,"name": "xs2","type":4},{"bits":7,"name": 0x73,"type":2}]} +.... + +Description:: +Atomically with acquire and release ordering: + + * Load the halfword at address _xs1_ + * Write the sign-extended value into _xd_ + * Unsigned compare the least-significant halfword of register _xs2_ to the loaded value, and select the maximum value + * Write the maximum to the address in _xs1_ + + +Decode Variables:: +[width="100%", cols="1,2", options="header"] +|=== +|Variable Name |Location +|xs2 |$encoding[24:20] +|xs1 |$encoding[19:15] +|xd |$encoding[11:7] +|=== + +Included in:: +[options="autowrap,autowidth"] +|=== +| Extension | Version + +| *Zabha* | ~> 1.0.0 + +|=== + + +[#udb:doc:inst:amomaxu_h_rl] +== amomaxu.h.rl + +Synopsis:: +Atomic MAX unsigned halfword (release) + +Assembly:: +amomaxu.h.rl xd, xs2, (xs1) + +Encoding:: +[wavedrom, ,svg,subs='attributes',width="100%"] +.... +{"reg":[{"bits":7,"name": 0x2f,"type":2},{"bits":5,"name": "xd","type":4},{"bits":3,"name": 0x1,"type":2},{"bits":5,"name": "xs1","type":4},{"bits":5,"name": "xs2","type":4},{"bits":7,"name": 0x71,"type":2}]} +.... + +Description:: +Atomically with release ordering: + + * Load the halfword at address _xs1_ + * Write the sign-extended value into _xd_ + * Unsigned compare the least-significant halfword of register _xs2_ to the loaded value, and select the maximum value + * Write the maximum to the address in _xs1_ + + +Decode Variables:: +[width="100%", cols="1,2", options="header"] +|=== +|Variable Name |Location +|xs2 |$encoding[24:20] +|xs1 |$encoding[19:15] +|xd |$encoding[11:7] +|=== + +Included in:: +[options="autowrap,autowidth"] +|=== +| Extension | Version + +| *Zabha* | ~> 1.0.0 + +|=== + + +[#udb:doc:inst:amomaxu_w] +== amomaxu.w + +Synopsis:: +Atomic MAX unsigned word + +Assembly:: +amomaxu.w xd, xs2, (xs1) + +Encoding:: +[wavedrom, ,svg,subs='attributes',width="100%"] +.... +{"reg":[{"bits":7,"name": 0x2f,"type":2},{"bits":5,"name": "xd","type":4},{"bits":3,"name": 0x2,"type":2},{"bits":5,"name": "xs1","type":4},{"bits":5,"name": "xs2","type":4},{"bits":7,"name": 0x70,"type":2}]} +.... + +Description:: +Atomically: + + * Load the word at address _xs1_ + * Write the sign-extended value into _xd_ + * Unsigned compare the least-significant word of register _xs2_ to the loaded value, and select the maximum value + * Write the maximum to the address in _xs1_ + + +Decode Variables:: +[width="100%", cols="1,2", options="header"] +|=== +|Variable Name |Location +|xs2 |$encoding[24:20] +|xs1 |$encoding[19:15] +|xd |$encoding[11:7] +|=== + +Included in:: +[options="autowrap,autowidth"] +|=== +| Extension | Version + +| *Zaamo* | ~> 1.0.0 + +|=== + + +[#udb:doc:inst:amomaxu_w_aq] +== amomaxu.w.aq + +Synopsis:: +Atomic MAX unsigned word (acquire) + +Assembly:: +amomaxu.w.aq xd, xs2, (xs1) + +Encoding:: +[wavedrom, ,svg,subs='attributes',width="100%"] +.... +{"reg":[{"bits":7,"name": 0x2f,"type":2},{"bits":5,"name": "xd","type":4},{"bits":3,"name": 0x2,"type":2},{"bits":5,"name": "xs1","type":4},{"bits":5,"name": "xs2","type":4},{"bits":7,"name": 0x72,"type":2}]} +.... + +Description:: +Atomically with acquire ordering: + + * Load the word at address _xs1_ + * Write the sign-extended value into _xd_ + * Unsigned compare the least-significant word of register _xs2_ to the loaded value, and select the maximum value + * Write the maximum to the address in _xs1_ + + +Decode Variables:: +[width="100%", cols="1,2", options="header"] +|=== +|Variable Name |Location +|xs2 |$encoding[24:20] +|xs1 |$encoding[19:15] +|xd |$encoding[11:7] +|=== + +Included in:: +[options="autowrap,autowidth"] +|=== +| Extension | Version + +| *Zaamo* | ~> 1.0.0 + +|=== + + +[#udb:doc:inst:amomaxu_w_aqrl] +== amomaxu.w.aqrl + +Synopsis:: +Atomic MAX unsigned word (acquire-release) + +Assembly:: +amomaxu.w.aqrl xd, xs2, (xs1) + +Encoding:: +[wavedrom, ,svg,subs='attributes',width="100%"] +.... +{"reg":[{"bits":7,"name": 0x2f,"type":2},{"bits":5,"name": "xd","type":4},{"bits":3,"name": 0x2,"type":2},{"bits":5,"name": "xs1","type":4},{"bits":5,"name": "xs2","type":4},{"bits":7,"name": 0x73,"type":2}]} +.... + +Description:: +Atomically with acquire and release ordering: + + * Load the word at address _xs1_ + * Write the sign-extended value into _xd_ + * Unsigned compare the least-significant word of register _xs2_ to the loaded value, and select the maximum value + * Write the maximum to the address in _xs1_ + + +Decode Variables:: +[width="100%", cols="1,2", options="header"] +|=== +|Variable Name |Location +|xs2 |$encoding[24:20] +|xs1 |$encoding[19:15] +|xd |$encoding[11:7] +|=== + +Included in:: +[options="autowrap,autowidth"] +|=== +| Extension | Version + +| *Zaamo* | ~> 1.0.0 + +|=== + + +[#udb:doc:inst:amomaxu_w_rl] +== amomaxu.w.rl + +Synopsis:: +Atomic MAX unsigned word (release) + +Assembly:: +amomaxu.w.rl xd, xs2, (xs1) + +Encoding:: +[wavedrom, ,svg,subs='attributes',width="100%"] +.... +{"reg":[{"bits":7,"name": 0x2f,"type":2},{"bits":5,"name": "xd","type":4},{"bits":3,"name": 0x2,"type":2},{"bits":5,"name": "xs1","type":4},{"bits":5,"name": "xs2","type":4},{"bits":7,"name": 0x71,"type":2}]} +.... + +Description:: +Atomically with release ordering: + + * Load the word at address _xs1_ + * Write the sign-extended value into _xd_ + * Unsigned compare the least-significant word of register _xs2_ to the loaded value, and select the maximum value + * Write the maximum to the address in _xs1_ + + +Decode Variables:: +[width="100%", cols="1,2", options="header"] +|=== +|Variable Name |Location +|xs2 |$encoding[24:20] +|xs1 |$encoding[19:15] +|xd |$encoding[11:7] +|=== + +Included in:: +[options="autowrap,autowidth"] +|=== +| Extension | Version + +| *Zaamo* | ~> 1.0.0 + +|=== + + +[#udb:doc:inst:amomin_b] +== amomin.b + +Synopsis:: +Atomic MIN byte + +Assembly:: +amomin.b xd, xs2, (xs1) + +Encoding:: +[wavedrom, ,svg,subs='attributes',width="100%"] +.... +{"reg":[{"bits":7,"name": 0x2f,"type":2},{"bits":5,"name": "xd","type":4},{"bits":3,"name": 0x0,"type":2},{"bits":5,"name": "xs1","type":4},{"bits":5,"name": "xs2","type":4},{"bits":7,"name": 0x40,"type":2}]} +.... + +Description:: +Atomically: + + * Load the byte at address _xs1_ + * Write the sign-extended value into _xd_ + * Signed compare the least-significant byte of register _xs2_ to the loaded value, and select the minimum value + * Write the minimum to the address in _xs1_ + + +Decode Variables:: +[width="100%", cols="1,2", options="header"] +|=== +|Variable Name |Location +|xs2 |$encoding[24:20] +|xs1 |$encoding[19:15] +|xd |$encoding[11:7] +|=== + +Included in:: +[options="autowrap,autowidth"] +|=== +| Extension | Version + +| *Zabha* | ~> 1.0.0 + +|=== + + +[#udb:doc:inst:amomin_b_aq] +== amomin.b.aq + +Synopsis:: +Atomic MIN byte (acquire) + +Assembly:: +amomin.b.aq xd, xs2, (xs1) + +Encoding:: +[wavedrom, ,svg,subs='attributes',width="100%"] +.... +{"reg":[{"bits":7,"name": 0x2f,"type":2},{"bits":5,"name": "xd","type":4},{"bits":3,"name": 0x0,"type":2},{"bits":5,"name": "xs1","type":4},{"bits":5,"name": "xs2","type":4},{"bits":7,"name": 0x42,"type":2}]} +.... + +Description:: +Atomically with acquire ordering: + + * Load the byte at address _xs1_ + * Write the sign-extended value into _xd_ + * Signed compare the least-significant byte of register _xs2_ to the loaded value, and select the minimum value + * Write the minimum to the address in _xs1_ + + +Decode Variables:: +[width="100%", cols="1,2", options="header"] +|=== +|Variable Name |Location +|xs2 |$encoding[24:20] +|xs1 |$encoding[19:15] +|xd |$encoding[11:7] +|=== + +Included in:: +[options="autowrap,autowidth"] +|=== +| Extension | Version + +| *Zabha* | ~> 1.0.0 + +|=== + + +[#udb:doc:inst:amomin_b_aqrl] +== amomin.b.aqrl + +Synopsis:: +Atomic MIN byte (acquire-release) + +Assembly:: +amomin.b.aqrl xd, xs2, (xs1) + +Encoding:: +[wavedrom, ,svg,subs='attributes',width="100%"] +.... +{"reg":[{"bits":7,"name": 0x2f,"type":2},{"bits":5,"name": "xd","type":4},{"bits":3,"name": 0x0,"type":2},{"bits":5,"name": "xs1","type":4},{"bits":5,"name": "xs2","type":4},{"bits":7,"name": 0x43,"type":2}]} +.... + +Description:: +Atomically with acquire and release ordering: + + * Load the byte at address _xs1_ + * Write the sign-extended value into _xd_ + * Signed compare the least-significant byte of register _xs2_ to the loaded value, and select the minimum value + * Write the minimum to the address in _xs1_ + + +Decode Variables:: +[width="100%", cols="1,2", options="header"] +|=== +|Variable Name |Location +|xs2 |$encoding[24:20] +|xs1 |$encoding[19:15] +|xd |$encoding[11:7] +|=== + +Included in:: +[options="autowrap,autowidth"] +|=== +| Extension | Version + +| *Zabha* | ~> 1.0.0 + +|=== + + +[#udb:doc:inst:amomin_b_rl] +== amomin.b.rl + +Synopsis:: +Atomic MIN byte (release) + +Assembly:: +amomin.b.rl xd, xs2, (xs1) + +Encoding:: +[wavedrom, ,svg,subs='attributes',width="100%"] +.... +{"reg":[{"bits":7,"name": 0x2f,"type":2},{"bits":5,"name": "xd","type":4},{"bits":3,"name": 0x0,"type":2},{"bits":5,"name": "xs1","type":4},{"bits":5,"name": "xs2","type":4},{"bits":7,"name": 0x41,"type":2}]} +.... + +Description:: +Atomically with release ordering: + + * Load the byte at address _xs1_ + * Write the sign-extended value into _xd_ + * Signed compare the least-significant byte of register _xs2_ to the loaded value, and select the minimum value + * Write the minimum to the address in _xs1_ + + +Decode Variables:: +[width="100%", cols="1,2", options="header"] +|=== +|Variable Name |Location +|xs2 |$encoding[24:20] +|xs1 |$encoding[19:15] +|xd |$encoding[11:7] +|=== + +Included in:: +[options="autowrap,autowidth"] +|=== +| Extension | Version + +| *Zabha* | ~> 1.0.0 + +|=== + + +[#udb:doc:inst:amomin_d] +== amomin.d + +Synopsis:: +Atomic MIN doubleword + +Assembly:: +amomin.d xd, xs2, (xs1) + +Encoding:: +[wavedrom, ,svg,subs='attributes',width="100%"] +.... +{"reg":[{"bits":7,"name": 0x2f,"type":2},{"bits":5,"name": "xd","type":4},{"bits":3,"name": 0x3,"type":2},{"bits":5,"name": "xs1","type":4},{"bits":5,"name": "xs2","type":4},{"bits":7,"name": 0x40,"type":2}]} +.... + +Description:: +Atomically: + + * Load the doubleword at address _xs1_ + * Write the loaded value into _xd_ + * Signed compare the value of register _xs2_ to the loaded value, and select the minimum value + * Write the minimum to the address in _xs1_ + + +Decode Variables:: +[width="100%", cols="1,2", options="header"] +|=== +|Variable Name |Location +|xs2 |$encoding[24:20] +|xs1 |$encoding[19:15] +|xd |$encoding[11:7] +|=== + +Included in:: +[options="autowrap,autowidth"] +|=== +| Extension | Version + +| *Zaamo* | ~> 1.0.0 + +|=== + + +[#udb:doc:inst:amomin_d_aq] +== amomin.d.aq + +Synopsis:: +Atomic MIN doubleword (acquire) + +Assembly:: +amomin.d.aq xd, xs2, (xs1) + +Encoding:: +[wavedrom, ,svg,subs='attributes',width="100%"] +.... +{"reg":[{"bits":7,"name": 0x2f,"type":2},{"bits":5,"name": "xd","type":4},{"bits":3,"name": 0x3,"type":2},{"bits":5,"name": "xs1","type":4},{"bits":5,"name": "xs2","type":4},{"bits":7,"name": 0x42,"type":2}]} +.... + +Description:: +Atomically with acquire ordering: + + * Load the doubleword at address _xs1_ + * Write the loaded value into _xd_ + * Signed compare the value of register _xs2_ to the loaded value, and select the minimum value + * Write the minimum to the address in _xs1_ + + +Decode Variables:: +[width="100%", cols="1,2", options="header"] +|=== +|Variable Name |Location +|xs2 |$encoding[24:20] +|xs1 |$encoding[19:15] +|xd |$encoding[11:7] +|=== + +Included in:: +[options="autowrap,autowidth"] +|=== +| Extension | Version + +| *Zaamo* | ~> 1.0.0 + +|=== + + +[#udb:doc:inst:amomin_d_aqrl] +== amomin.d.aqrl + +Synopsis:: +Atomic MIN doubleword (acquire-release) + +Assembly:: +amomin.d.aqrl xd, xs2, (xs1) + +Encoding:: +[wavedrom, ,svg,subs='attributes',width="100%"] +.... +{"reg":[{"bits":7,"name": 0x2f,"type":2},{"bits":5,"name": "xd","type":4},{"bits":3,"name": 0x3,"type":2},{"bits":5,"name": "xs1","type":4},{"bits":5,"name": "xs2","type":4},{"bits":7,"name": 0x43,"type":2}]} +.... + +Description:: +Atomically with acquire and release ordering: + + * Load the doubleword at address _xs1_ + * Write the loaded value into _xd_ + * Signed compare the value of register _xs2_ to the loaded value, and select the minimum value + * Write the minimum to the address in _xs1_ + + +Decode Variables:: +[width="100%", cols="1,2", options="header"] +|=== +|Variable Name |Location +|xs2 |$encoding[24:20] +|xs1 |$encoding[19:15] +|xd |$encoding[11:7] +|=== + +Included in:: +[options="autowrap,autowidth"] +|=== +| Extension | Version + +| *Zaamo* | ~> 1.0.0 + +|=== + + +[#udb:doc:inst:amomin_d_rl] +== amomin.d.rl + +Synopsis:: +Atomic MIN doubleword (release) + +Assembly:: +amomin.d.rl xd, xs2, (xs1) + +Encoding:: +[wavedrom, ,svg,subs='attributes',width="100%"] +.... +{"reg":[{"bits":7,"name": 0x2f,"type":2},{"bits":5,"name": "xd","type":4},{"bits":3,"name": 0x3,"type":2},{"bits":5,"name": "xs1","type":4},{"bits":5,"name": "xs2","type":4},{"bits":7,"name": 0x41,"type":2}]} +.... + +Description:: +Atomically with release ordering: + + * Load the doubleword at address _xs1_ + * Write the loaded value into _xd_ + * Signed compare the value of register _xs2_ to the loaded value, and select the minimum value + * Write the minimum to the address in _xs1_ + + +Decode Variables:: +[width="100%", cols="1,2", options="header"] +|=== +|Variable Name |Location +|xs2 |$encoding[24:20] +|xs1 |$encoding[19:15] +|xd |$encoding[11:7] +|=== + +Included in:: +[options="autowrap,autowidth"] +|=== +| Extension | Version + +| *Zaamo* | ~> 1.0.0 + +|=== + + +[#udb:doc:inst:amomin_h] +== amomin.h + +Synopsis:: +Atomic MIN halfword + +Assembly:: +amomin.h xd, xs2, (xs1) + +Encoding:: +[wavedrom, ,svg,subs='attributes',width="100%"] +.... +{"reg":[{"bits":7,"name": 0x2f,"type":2},{"bits":5,"name": "xd","type":4},{"bits":3,"name": 0x1,"type":2},{"bits":5,"name": "xs1","type":4},{"bits":5,"name": "xs2","type":4},{"bits":7,"name": 0x40,"type":2}]} +.... + +Description:: +Atomically: + + * Load the halfword at address _xs1_ + * Write the sign-extended value into _xd_ + * Signed compare the least-significant halfword of register _xs2_ to the loaded value, and select the minimum value + * Write the minimum to the address in _xs1_ + + +Decode Variables:: +[width="100%", cols="1,2", options="header"] +|=== +|Variable Name |Location +|xs2 |$encoding[24:20] +|xs1 |$encoding[19:15] +|xd |$encoding[11:7] +|=== + +Included in:: +[options="autowrap,autowidth"] +|=== +| Extension | Version + +| *Zabha* | ~> 1.0.0 + +|=== + + +[#udb:doc:inst:amomin_h_aq] +== amomin.h.aq + +Synopsis:: +Atomic MIN halfword (acquire) + +Assembly:: +amomin.h.aq xd, xs2, (xs1) + +Encoding:: +[wavedrom, ,svg,subs='attributes',width="100%"] +.... +{"reg":[{"bits":7,"name": 0x2f,"type":2},{"bits":5,"name": "xd","type":4},{"bits":3,"name": 0x1,"type":2},{"bits":5,"name": "xs1","type":4},{"bits":5,"name": "xs2","type":4},{"bits":7,"name": 0x42,"type":2}]} +.... + +Description:: +Atomically with acquire ordering: + + * Load the halfword at address _xs1_ + * Write the sign-extended value into _xd_ + * Signed compare the least-significant halfword of register _xs2_ to the loaded value, and select the minimum value + * Write the minimum to the address in _xs1_ + + +Decode Variables:: +[width="100%", cols="1,2", options="header"] +|=== +|Variable Name |Location +|xs2 |$encoding[24:20] +|xs1 |$encoding[19:15] +|xd |$encoding[11:7] +|=== + +Included in:: +[options="autowrap,autowidth"] +|=== +| Extension | Version + +| *Zabha* | ~> 1.0.0 + +|=== + + +[#udb:doc:inst:amomin_h_aqrl] +== amomin.h.aqrl + +Synopsis:: +Atomic MIN halfword (acquire-release) + +Assembly:: +amomin.h.aqrl xd, xs2, (xs1) + +Encoding:: +[wavedrom, ,svg,subs='attributes',width="100%"] +.... +{"reg":[{"bits":7,"name": 0x2f,"type":2},{"bits":5,"name": "xd","type":4},{"bits":3,"name": 0x1,"type":2},{"bits":5,"name": "xs1","type":4},{"bits":5,"name": "xs2","type":4},{"bits":7,"name": 0x43,"type":2}]} +.... + +Description:: +Atomically with acquire and release ordering: + + * Load the halfword at address _xs1_ + * Write the sign-extended value into _xd_ + * Signed compare the least-significant halfword of register _xs2_ to the loaded value, and select the minimum value + * Write the minimum to the address in _xs1_ + + +Decode Variables:: +[width="100%", cols="1,2", options="header"] +|=== +|Variable Name |Location +|xs2 |$encoding[24:20] +|xs1 |$encoding[19:15] +|xd |$encoding[11:7] +|=== + +Included in:: +[options="autowrap,autowidth"] +|=== +| Extension | Version + +| *Zabha* | ~> 1.0.0 + +|=== + + +[#udb:doc:inst:amomin_h_rl] +== amomin.h.rl + +Synopsis:: +Atomic MIN halfword (release) + +Assembly:: +amomin.h.rl xd, xs2, (xs1) + +Encoding:: +[wavedrom, ,svg,subs='attributes',width="100%"] +.... +{"reg":[{"bits":7,"name": 0x2f,"type":2},{"bits":5,"name": "xd","type":4},{"bits":3,"name": 0x1,"type":2},{"bits":5,"name": "xs1","type":4},{"bits":5,"name": "xs2","type":4},{"bits":7,"name": 0x41,"type":2}]} +.... + +Description:: +Atomically with release ordering: + + * Load the halfword at address _xs1_ + * Write the sign-extended value into _xd_ + * Signed compare the least-significant halfword of register _xs2_ to the loaded value, and select the minimum value + * Write the minimum to the address in _xs1_ + + +Decode Variables:: +[width="100%", cols="1,2", options="header"] +|=== +|Variable Name |Location +|xs2 |$encoding[24:20] +|xs1 |$encoding[19:15] +|xd |$encoding[11:7] +|=== + +Included in:: +[options="autowrap,autowidth"] +|=== +| Extension | Version + +| *Zabha* | ~> 1.0.0 + +|=== + + +[#udb:doc:inst:amomin_w] +== amomin.w + +Synopsis:: +Atomic MIN word + +Assembly:: +amomin.w xd, xs2, (xs1) + +Encoding:: +[wavedrom, ,svg,subs='attributes',width="100%"] +.... +{"reg":[{"bits":7,"name": 0x2f,"type":2},{"bits":5,"name": "xd","type":4},{"bits":3,"name": 0x2,"type":2},{"bits":5,"name": "xs1","type":4},{"bits":5,"name": "xs2","type":4},{"bits":7,"name": 0x40,"type":2}]} +.... + +Description:: +Atomically: + + * Load the word at address _xs1_ + * Write the sign-extended value into _xd_ + * Signed compare the least-significant word of register _xs2_ to the loaded value, and select the minimum value + * Write the minimum to the address in _xs1_ + + +Decode Variables:: +[width="100%", cols="1,2", options="header"] +|=== +|Variable Name |Location +|xs2 |$encoding[24:20] +|xs1 |$encoding[19:15] +|xd |$encoding[11:7] +|=== + +Included in:: +[options="autowrap,autowidth"] +|=== +| Extension | Version + +| *Zaamo* | ~> 1.0.0 + +|=== + + +[#udb:doc:inst:amomin_w_aq] +== amomin.w.aq + +Synopsis:: +Atomic MIN word (acquire) + +Assembly:: +amomin.w.aq xd, xs2, (xs1) + +Encoding:: +[wavedrom, ,svg,subs='attributes',width="100%"] +.... +{"reg":[{"bits":7,"name": 0x2f,"type":2},{"bits":5,"name": "xd","type":4},{"bits":3,"name": 0x2,"type":2},{"bits":5,"name": "xs1","type":4},{"bits":5,"name": "xs2","type":4},{"bits":7,"name": 0x42,"type":2}]} +.... + +Description:: +Atomically with acquire ordering: + + * Load the word at address _xs1_ + * Write the sign-extended value into _xd_ + * Signed compare the least-significant word of register _xs2_ to the loaded value, and select the minimum value + * Write the minimum to the address in _xs1_ + + +Decode Variables:: +[width="100%", cols="1,2", options="header"] +|=== +|Variable Name |Location +|xs2 |$encoding[24:20] +|xs1 |$encoding[19:15] +|xd |$encoding[11:7] +|=== + +Included in:: +[options="autowrap,autowidth"] +|=== +| Extension | Version + +| *Zaamo* | ~> 1.0.0 + +|=== + + +[#udb:doc:inst:amomin_w_aqrl] +== amomin.w.aqrl + +Synopsis:: +Atomic MIN word (acquire-release) + +Assembly:: +amomin.w.aqrl xd, xs2, (xs1) + +Encoding:: +[wavedrom, ,svg,subs='attributes',width="100%"] +.... +{"reg":[{"bits":7,"name": 0x2f,"type":2},{"bits":5,"name": "xd","type":4},{"bits":3,"name": 0x2,"type":2},{"bits":5,"name": "xs1","type":4},{"bits":5,"name": "xs2","type":4},{"bits":7,"name": 0x43,"type":2}]} +.... + +Description:: +Atomically with acquire and release ordering: + + * Load the word at address _xs1_ + * Write the sign-extended value into _xd_ + * Signed compare the least-significant word of register _xs2_ to the loaded value, and select the minimum value + * Write the minimum to the address in _xs1_ + + +Decode Variables:: +[width="100%", cols="1,2", options="header"] +|=== +|Variable Name |Location +|xs2 |$encoding[24:20] +|xs1 |$encoding[19:15] +|xd |$encoding[11:7] +|=== + +Included in:: +[options="autowrap,autowidth"] +|=== +| Extension | Version + +| *Zaamo* | ~> 1.0.0 + +|=== + + +[#udb:doc:inst:amomin_w_rl] +== amomin.w.rl + +Synopsis:: +Atomic MIN word (release) + +Assembly:: +amomin.w.rl xd, xs2, (xs1) + +Encoding:: +[wavedrom, ,svg,subs='attributes',width="100%"] +.... +{"reg":[{"bits":7,"name": 0x2f,"type":2},{"bits":5,"name": "xd","type":4},{"bits":3,"name": 0x2,"type":2},{"bits":5,"name": "xs1","type":4},{"bits":5,"name": "xs2","type":4},{"bits":7,"name": 0x41,"type":2}]} +.... + +Description:: +Atomically with release ordering: + + * Load the word at address _xs1_ + * Write the sign-extended value into _xd_ + * Signed compare the least-significant word of register _xs2_ to the loaded value, and select the minimum value + * Write the minimum to the address in _xs1_ + + +Decode Variables:: +[width="100%", cols="1,2", options="header"] +|=== +|Variable Name |Location +|xs2 |$encoding[24:20] +|xs1 |$encoding[19:15] +|xd |$encoding[11:7] +|=== + +Included in:: +[options="autowrap,autowidth"] +|=== +| Extension | Version + +| *Zaamo* | ~> 1.0.0 + +|=== + + +[#udb:doc:inst:amominu_b] +== amominu.b + +Synopsis:: +Atomic MIN unsigned byte + +Assembly:: +amominu.b xd, xs2, (xs1) + +Encoding:: +[wavedrom, ,svg,subs='attributes',width="100%"] +.... +{"reg":[{"bits":7,"name": 0x2f,"type":2},{"bits":5,"name": "xd","type":4},{"bits":3,"name": 0x0,"type":2},{"bits":5,"name": "xs1","type":4},{"bits":5,"name": "xs2","type":4},{"bits":7,"name": 0x60,"type":2}]} +.... + +Description:: +Atomically: + + * Load the byte at address _xs1_ + * Write the sign-extended value into _xd_ + * Unsigned compare the least-significant byte of register _xs2_ to the loaded value, and select the minimum value + * Write the minimum to the address in _xs1_ + + +Decode Variables:: +[width="100%", cols="1,2", options="header"] +|=== +|Variable Name |Location +|xs2 |$encoding[24:20] +|xs1 |$encoding[19:15] +|xd |$encoding[11:7] +|=== + +Included in:: +[options="autowrap,autowidth"] +|=== +| Extension | Version + +| *Zabha* | ~> 1.0.0 + +|=== + + +[#udb:doc:inst:amominu_b_aq] +== amominu.b.aq + +Synopsis:: +Atomic MIN unsigned byte (acquire) + +Assembly:: +amominu.b.aq xd, xs2, (xs1) + +Encoding:: +[wavedrom, ,svg,subs='attributes',width="100%"] +.... +{"reg":[{"bits":7,"name": 0x2f,"type":2},{"bits":5,"name": "xd","type":4},{"bits":3,"name": 0x0,"type":2},{"bits":5,"name": "xs1","type":4},{"bits":5,"name": "xs2","type":4},{"bits":7,"name": 0x62,"type":2}]} +.... + +Description:: +Atomically with acquire ordering: + + * Load the byte at address _xs1_ + * Write the sign-extended value into _xd_ + * Unsigned compare the least-significant byte of register _xs2_ to the loaded value, and select the minimum value + * Write the minimum to the address in _xs1_ + + +Decode Variables:: +[width="100%", cols="1,2", options="header"] +|=== +|Variable Name |Location +|xs2 |$encoding[24:20] +|xs1 |$encoding[19:15] +|xd |$encoding[11:7] +|=== + +Included in:: +[options="autowrap,autowidth"] +|=== +| Extension | Version + +| *Zabha* | ~> 1.0.0 + +|=== + + +[#udb:doc:inst:amominu_b_aqrl] +== amominu.b.aqrl + +Synopsis:: +Atomic MIN unsigned byte (acquire-release) + +Assembly:: +amominu.b.aqrl xd, xs2, (xs1) + +Encoding:: +[wavedrom, ,svg,subs='attributes',width="100%"] +.... +{"reg":[{"bits":7,"name": 0x2f,"type":2},{"bits":5,"name": "xd","type":4},{"bits":3,"name": 0x0,"type":2},{"bits":5,"name": "xs1","type":4},{"bits":5,"name": "xs2","type":4},{"bits":7,"name": 0x63,"type":2}]} +.... + +Description:: +Atomically with acquire and release ordering: + + * Load the byte at address _xs1_ + * Write the sign-extended value into _xd_ + * Unsigned compare the least-significant byte of register _xs2_ to the loaded value, and select the minimum value + * Write the minimum to the address in _xs1_ + + +Decode Variables:: +[width="100%", cols="1,2", options="header"] +|=== +|Variable Name |Location +|xs2 |$encoding[24:20] +|xs1 |$encoding[19:15] +|xd |$encoding[11:7] +|=== + +Included in:: +[options="autowrap,autowidth"] +|=== +| Extension | Version + +| *Zabha* | ~> 1.0.0 + +|=== + + +[#udb:doc:inst:amominu_b_rl] +== amominu.b.rl + +Synopsis:: +Atomic MIN unsigned byte (release) + +Assembly:: +amominu.b.rl xd, xs2, (xs1) + +Encoding:: +[wavedrom, ,svg,subs='attributes',width="100%"] +.... +{"reg":[{"bits":7,"name": 0x2f,"type":2},{"bits":5,"name": "xd","type":4},{"bits":3,"name": 0x0,"type":2},{"bits":5,"name": "xs1","type":4},{"bits":5,"name": "xs2","type":4},{"bits":7,"name": 0x61,"type":2}]} +.... + +Description:: +Atomically with release ordering: + + * Load the byte at address _xs1_ + * Write the sign-extended value into _xd_ + * Unsigned compare the least-significant byte of register _xs2_ to the loaded value, and select the minimum value + * Write the minimum to the address in _xs1_ + + +Decode Variables:: +[width="100%", cols="1,2", options="header"] +|=== +|Variable Name |Location +|xs2 |$encoding[24:20] +|xs1 |$encoding[19:15] +|xd |$encoding[11:7] +|=== + +Included in:: +[options="autowrap,autowidth"] +|=== +| Extension | Version + +| *Zabha* | ~> 1.0.0 + +|=== + + +[#udb:doc:inst:amominu_d] +== amominu.d + +Synopsis:: +Atomic MIN unsigned doubleword + +Assembly:: +amominu.d xd, xs2, (xs1) + +Encoding:: +[wavedrom, ,svg,subs='attributes',width="100%"] +.... +{"reg":[{"bits":7,"name": 0x2f,"type":2},{"bits":5,"name": "xd","type":4},{"bits":3,"name": 0x3,"type":2},{"bits":5,"name": "xs1","type":4},{"bits":5,"name": "xs2","type":4},{"bits":7,"name": 0x60,"type":2}]} +.... + +Description:: +Atomically: + + * Load the doubleword at address _xs1_ + * Write the loaded value into _xd_ + * Unsigned compare the value of register _xs2_ to the loaded value, and select the minimum value + * Write the minimum to the address in _xs1_ + + +Decode Variables:: +[width="100%", cols="1,2", options="header"] +|=== +|Variable Name |Location +|xs2 |$encoding[24:20] +|xs1 |$encoding[19:15] +|xd |$encoding[11:7] +|=== + +Included in:: +[options="autowrap,autowidth"] +|=== +| Extension | Version + +| *Zaamo* | ~> 1.0.0 + +|=== + + +[#udb:doc:inst:amominu_d_aq] +== amominu.d.aq + +Synopsis:: +Atomic MIN unsigned doubleword (acquire) + +Assembly:: +amominu.d.aq xd, xs2, (xs1) + +Encoding:: +[wavedrom, ,svg,subs='attributes',width="100%"] +.... +{"reg":[{"bits":7,"name": 0x2f,"type":2},{"bits":5,"name": "xd","type":4},{"bits":3,"name": 0x3,"type":2},{"bits":5,"name": "xs1","type":4},{"bits":5,"name": "xs2","type":4},{"bits":7,"name": 0x62,"type":2}]} +.... + +Description:: +Atomically with acquire ordering: + + * Load the doubleword at address _xs1_ + * Write the loaded value into _xd_ + * Unsigned compare the value of register _xs2_ to the loaded value, and select the minimum value + * Write the minimum to the address in _xs1_ + + +Decode Variables:: +[width="100%", cols="1,2", options="header"] +|=== +|Variable Name |Location +|xs2 |$encoding[24:20] +|xs1 |$encoding[19:15] +|xd |$encoding[11:7] +|=== + +Included in:: +[options="autowrap,autowidth"] +|=== +| Extension | Version + +| *Zaamo* | ~> 1.0.0 + +|=== + + +[#udb:doc:inst:amominu_d_aqrl] +== amominu.d.aqrl + +Synopsis:: +Atomic MIN unsigned doubleword (acquire-release) + +Assembly:: +amominu.d.aqrl xd, xs2, (xs1) + +Encoding:: +[wavedrom, ,svg,subs='attributes',width="100%"] +.... +{"reg":[{"bits":7,"name": 0x2f,"type":2},{"bits":5,"name": "xd","type":4},{"bits":3,"name": 0x3,"type":2},{"bits":5,"name": "xs1","type":4},{"bits":5,"name": "xs2","type":4},{"bits":7,"name": 0x63,"type":2}]} +.... + +Description:: +Atomically with acquire and release ordering: + + * Load the doubleword at address _xs1_ + * Write the loaded value into _xd_ + * Unsigned compare the value of register _xs2_ to the loaded value, and select the minimum value + * Write the minimum to the address in _xs1_ + + +Decode Variables:: +[width="100%", cols="1,2", options="header"] +|=== +|Variable Name |Location +|xs2 |$encoding[24:20] +|xs1 |$encoding[19:15] +|xd |$encoding[11:7] +|=== + +Included in:: +[options="autowrap,autowidth"] +|=== +| Extension | Version + +| *Zaamo* | ~> 1.0.0 + +|=== + + +[#udb:doc:inst:amominu_d_rl] +== amominu.d.rl + +Synopsis:: +Atomic MIN unsigned doubleword (release) + +Assembly:: +amominu.d.rl xd, xs2, (xs1) + +Encoding:: +[wavedrom, ,svg,subs='attributes',width="100%"] +.... +{"reg":[{"bits":7,"name": 0x2f,"type":2},{"bits":5,"name": "xd","type":4},{"bits":3,"name": 0x3,"type":2},{"bits":5,"name": "xs1","type":4},{"bits":5,"name": "xs2","type":4},{"bits":7,"name": 0x61,"type":2}]} +.... + +Description:: +Atomically with release ordering: + + * Load the doubleword at address _xs1_ + * Write the loaded value into _xd_ + * Unsigned compare the value of register _xs2_ to the loaded value, and select the minimum value + * Write the minimum to the address in _xs1_ + + +Decode Variables:: +[width="100%", cols="1,2", options="header"] +|=== +|Variable Name |Location +|xs2 |$encoding[24:20] +|xs1 |$encoding[19:15] +|xd |$encoding[11:7] +|=== + +Included in:: +[options="autowrap,autowidth"] +|=== +| Extension | Version + +| *Zaamo* | ~> 1.0.0 + +|=== + + +[#udb:doc:inst:amominu_h] +== amominu.h + +Synopsis:: +Atomic MIN unsigned halfword + +Assembly:: +amominu.h xd, xs2, (xs1) + +Encoding:: +[wavedrom, ,svg,subs='attributes',width="100%"] +.... +{"reg":[{"bits":7,"name": 0x2f,"type":2},{"bits":5,"name": "xd","type":4},{"bits":3,"name": 0x1,"type":2},{"bits":5,"name": "xs1","type":4},{"bits":5,"name": "xs2","type":4},{"bits":7,"name": 0x60,"type":2}]} +.... + +Description:: +Atomically: + + * Load the halfword at address _xs1_ + * Write the sign-extended value into _xd_ + * Unsigned compare the least-significant halfword of register _xs2_ to the loaded value, and select the minimum value + * Write the minimum to the address in _xs1_ + + +Decode Variables:: +[width="100%", cols="1,2", options="header"] +|=== +|Variable Name |Location +|xs2 |$encoding[24:20] +|xs1 |$encoding[19:15] +|xd |$encoding[11:7] +|=== + +Included in:: +[options="autowrap,autowidth"] +|=== +| Extension | Version + +| *Zabha* | ~> 1.0.0 + +|=== + + +[#udb:doc:inst:amominu_h_aq] +== amominu.h.aq + +Synopsis:: +Atomic MIN unsigned halfword (acquire) + +Assembly:: +amominu.h.aq xd, xs2, (xs1) + +Encoding:: +[wavedrom, ,svg,subs='attributes',width="100%"] +.... +{"reg":[{"bits":7,"name": 0x2f,"type":2},{"bits":5,"name": "xd","type":4},{"bits":3,"name": 0x1,"type":2},{"bits":5,"name": "xs1","type":4},{"bits":5,"name": "xs2","type":4},{"bits":7,"name": 0x62,"type":2}]} +.... + +Description:: +Atomically with acquire ordering: + + * Load the halfword at address _xs1_ + * Write the sign-extended value into _xd_ + * Unsigned compare the least-significant halfword of register _xs2_ to the loaded value, and select the minimum value + * Write the minimum to the address in _xs1_ + + +Decode Variables:: +[width="100%", cols="1,2", options="header"] +|=== +|Variable Name |Location +|xs2 |$encoding[24:20] +|xs1 |$encoding[19:15] +|xd |$encoding[11:7] +|=== + +Included in:: +[options="autowrap,autowidth"] +|=== +| Extension | Version + +| *Zabha* | ~> 1.0.0 + +|=== + + +[#udb:doc:inst:amominu_h_aqrl] +== amominu.h.aqrl + +Synopsis:: +Atomic MIN unsigned halfword (acquire-release) + +Assembly:: +amominu.h.aqrl xd, xs2, (xs1) + +Encoding:: +[wavedrom, ,svg,subs='attributes',width="100%"] +.... +{"reg":[{"bits":7,"name": 0x2f,"type":2},{"bits":5,"name": "xd","type":4},{"bits":3,"name": 0x1,"type":2},{"bits":5,"name": "xs1","type":4},{"bits":5,"name": "xs2","type":4},{"bits":7,"name": 0x63,"type":2}]} +.... + +Description:: +Atomically with acquire and release ordering: + + * Load the halfword at address _xs1_ + * Write the sign-extended value into _xd_ + * Unsigned compare the least-significant halfword of register _xs2_ to the loaded value, and select the minimum value + * Write the minimum to the address in _xs1_ + + +Decode Variables:: +[width="100%", cols="1,2", options="header"] +|=== +|Variable Name |Location +|xs2 |$encoding[24:20] +|xs1 |$encoding[19:15] +|xd |$encoding[11:7] +|=== + +Included in:: +[options="autowrap,autowidth"] +|=== +| Extension | Version + +| *Zabha* | ~> 1.0.0 + +|=== + + +[#udb:doc:inst:amominu_h_rl] +== amominu.h.rl + +Synopsis:: +Atomic MIN unsigned halfword (release) + +Assembly:: +amominu.h.rl xd, xs2, (xs1) + +Encoding:: +[wavedrom, ,svg,subs='attributes',width="100%"] +.... +{"reg":[{"bits":7,"name": 0x2f,"type":2},{"bits":5,"name": "xd","type":4},{"bits":3,"name": 0x1,"type":2},{"bits":5,"name": "xs1","type":4},{"bits":5,"name": "xs2","type":4},{"bits":7,"name": 0x61,"type":2}]} +.... + +Description:: +Atomically with release ordering: + + * Load the halfword at address _xs1_ + * Write the sign-extended value into _xd_ + * Unsigned compare the least-significant halfword of register _xs2_ to the loaded value, and select the minimum value + * Write the minimum to the address in _xs1_ + + +Decode Variables:: +[width="100%", cols="1,2", options="header"] +|=== +|Variable Name |Location +|xs2 |$encoding[24:20] +|xs1 |$encoding[19:15] +|xd |$encoding[11:7] +|=== + +Included in:: +[options="autowrap,autowidth"] +|=== +| Extension | Version + +| *Zabha* | ~> 1.0.0 + +|=== + + +[#udb:doc:inst:amominu_w] +== amominu.w + +Synopsis:: +Atomic MIN unsigned word + +Assembly:: +amominu.w xd, xs2, (xs1) + +Encoding:: +[wavedrom, ,svg,subs='attributes',width="100%"] +.... +{"reg":[{"bits":7,"name": 0x2f,"type":2},{"bits":5,"name": "xd","type":4},{"bits":3,"name": 0x2,"type":2},{"bits":5,"name": "xs1","type":4},{"bits":5,"name": "xs2","type":4},{"bits":7,"name": 0x60,"type":2}]} +.... + +Description:: +Atomically: + + * Load the word at address _xs1_ + * Write the sign-extended value into _xd_ + * Unsigned compare the least-significant word of register _xs2_ to the loaded value, and select the minimum value + * Write the minimum to the address in _xs1_ + + +Decode Variables:: +[width="100%", cols="1,2", options="header"] +|=== +|Variable Name |Location +|xs2 |$encoding[24:20] +|xs1 |$encoding[19:15] +|xd |$encoding[11:7] +|=== + +Included in:: +[options="autowrap,autowidth"] +|=== +| Extension | Version + +| *Zaamo* | ~> 1.0.0 + +|=== + + +[#udb:doc:inst:amominu_w_aq] +== amominu.w.aq + +Synopsis:: +Atomic MIN unsigned word (acquire) + +Assembly:: +amominu.w.aq xd, xs2, (xs1) + +Encoding:: +[wavedrom, ,svg,subs='attributes',width="100%"] +.... +{"reg":[{"bits":7,"name": 0x2f,"type":2},{"bits":5,"name": "xd","type":4},{"bits":3,"name": 0x2,"type":2},{"bits":5,"name": "xs1","type":4},{"bits":5,"name": "xs2","type":4},{"bits":7,"name": 0x62,"type":2}]} +.... + +Description:: +Atomically with acquire ordering: + + * Load the word at address _xs1_ + * Write the sign-extended value into _xd_ + * Unsigned compare the least-significant word of register _xs2_ to the loaded value, and select the minimum value + * Write the minimum to the address in _xs1_ + + +Decode Variables:: +[width="100%", cols="1,2", options="header"] +|=== +|Variable Name |Location +|xs2 |$encoding[24:20] +|xs1 |$encoding[19:15] +|xd |$encoding[11:7] +|=== + +Included in:: +[options="autowrap,autowidth"] +|=== +| Extension | Version + +| *Zaamo* | ~> 1.0.0 + +|=== + + +[#udb:doc:inst:amominu_w_aqrl] +== amominu.w.aqrl + +Synopsis:: +Atomic MIN unsigned word (acquire-release) + +Assembly:: +amominu.w.aqrl xd, xs2, (xs1) + +Encoding:: +[wavedrom, ,svg,subs='attributes',width="100%"] +.... +{"reg":[{"bits":7,"name": 0x2f,"type":2},{"bits":5,"name": "xd","type":4},{"bits":3,"name": 0x2,"type":2},{"bits":5,"name": "xs1","type":4},{"bits":5,"name": "xs2","type":4},{"bits":7,"name": 0x63,"type":2}]} +.... + +Description:: +Atomically with acquire and release ordering: + + * Load the word at address _xs1_ + * Write the sign-extended value into _xd_ + * Unsigned compare the least-significant word of register _xs2_ to the loaded value, and select the minimum value + * Write the minimum to the address in _xs1_ + + +Decode Variables:: +[width="100%", cols="1,2", options="header"] +|=== +|Variable Name |Location +|xs2 |$encoding[24:20] +|xs1 |$encoding[19:15] +|xd |$encoding[11:7] +|=== + +Included in:: +[options="autowrap,autowidth"] +|=== +| Extension | Version + +| *Zaamo* | ~> 1.0.0 + +|=== + + +[#udb:doc:inst:amominu_w_rl] +== amominu.w.rl + +Synopsis:: +Atomic MIN unsigned word (release) + +Assembly:: +amominu.w.rl xd, xs2, (xs1) + +Encoding:: +[wavedrom, ,svg,subs='attributes',width="100%"] +.... +{"reg":[{"bits":7,"name": 0x2f,"type":2},{"bits":5,"name": "xd","type":4},{"bits":3,"name": 0x2,"type":2},{"bits":5,"name": "xs1","type":4},{"bits":5,"name": "xs2","type":4},{"bits":7,"name": 0x61,"type":2}]} +.... + +Description:: +Atomically with release ordering: + + * Load the word at address _xs1_ + * Write the sign-extended value into _xd_ + * Unsigned compare the least-significant word of register _xs2_ to the loaded value, and select the minimum value + * Write the minimum to the address in _xs1_ + + +Decode Variables:: +[width="100%", cols="1,2", options="header"] +|=== +|Variable Name |Location +|xs2 |$encoding[24:20] +|xs1 |$encoding[19:15] +|xd |$encoding[11:7] +|=== + +Included in:: +[options="autowrap,autowidth"] +|=== +| Extension | Version + +| *Zaamo* | ~> 1.0.0 + +|=== + + +[#udb:doc:inst:amoor_b] +== amoor.b + +Synopsis:: +Atomic fetch-and-or byte + +Assembly:: +amoor.b xd, xs2, (xs1) + +Encoding:: +[wavedrom, ,svg,subs='attributes',width="100%"] +.... +{"reg":[{"bits":7,"name": 0x2f,"type":2},{"bits":5,"name": "xd","type":4},{"bits":3,"name": 0x0,"type":2},{"bits":5,"name": "xs1","type":4},{"bits":5,"name": "xs2","type":4},{"bits":7,"name": 0x20,"type":2}]} +.... + +Description:: +Atomically: + + * Load the byte at address _xs1_ + * Write the sign-extended value into _xd_ + * OR the least-significant byte of register _xs2_ to the loaded value + * Write the result to the address in _xs1_ + + +Decode Variables:: +[width="100%", cols="1,2", options="header"] +|=== +|Variable Name |Location +|xs2 |$encoding[24:20] +|xs1 |$encoding[19:15] +|xd |$encoding[11:7] +|=== + +Included in:: +[options="autowrap,autowidth"] +|=== +| Extension | Version + +| *Zabha* | ~> 1.0.0 + +|=== + + +[#udb:doc:inst:amoor_b_aq] +== amoor.b.aq + +Synopsis:: +Atomic fetch-and-or byte (acquire) + +Assembly:: +amoor.b.aq xd, xs2, (xs1) + +Encoding:: +[wavedrom, ,svg,subs='attributes',width="100%"] +.... +{"reg":[{"bits":7,"name": 0x2f,"type":2},{"bits":5,"name": "xd","type":4},{"bits":3,"name": 0x0,"type":2},{"bits":5,"name": "xs1","type":4},{"bits":5,"name": "xs2","type":4},{"bits":7,"name": 0x22,"type":2}]} +.... + +Description:: +Atomically with acquire ordering: + + * Load the byte at address _xs1_ + * Write the sign-extended value into _xd_ + * OR the least-significant byte of register _xs2_ to the loaded value + * Write the result to the address in _xs1_ + + +Decode Variables:: +[width="100%", cols="1,2", options="header"] +|=== +|Variable Name |Location +|xs2 |$encoding[24:20] +|xs1 |$encoding[19:15] +|xd |$encoding[11:7] +|=== + +Included in:: +[options="autowrap,autowidth"] +|=== +| Extension | Version + +| *Zabha* | ~> 1.0.0 + +|=== + + +[#udb:doc:inst:amoor_b_aqrl] +== amoor.b.aqrl + +Synopsis:: +Atomic fetch-and-or byte (acquire-release) + +Assembly:: +amoor.b.aqrl xd, xs2, (xs1) + +Encoding:: +[wavedrom, ,svg,subs='attributes',width="100%"] +.... +{"reg":[{"bits":7,"name": 0x2f,"type":2},{"bits":5,"name": "xd","type":4},{"bits":3,"name": 0x0,"type":2},{"bits":5,"name": "xs1","type":4},{"bits":5,"name": "xs2","type":4},{"bits":7,"name": 0x23,"type":2}]} +.... + +Description:: +Atomically with acquire and release ordering: + + * Load the byte at address _xs1_ + * Write the sign-extended value into _xd_ + * OR the least-significant byte of register _xs2_ to the loaded value + * Write the result to the address in _xs1_ + + +Decode Variables:: +[width="100%", cols="1,2", options="header"] +|=== +|Variable Name |Location +|xs2 |$encoding[24:20] +|xs1 |$encoding[19:15] +|xd |$encoding[11:7] +|=== + +Included in:: +[options="autowrap,autowidth"] +|=== +| Extension | Version + +| *Zabha* | ~> 1.0.0 + +|=== + + +[#udb:doc:inst:amoor_b_rl] +== amoor.b.rl + +Synopsis:: +Atomic fetch-and-or byte (release) + +Assembly:: +amoor.b.rl xd, xs2, (xs1) + +Encoding:: +[wavedrom, ,svg,subs='attributes',width="100%"] +.... +{"reg":[{"bits":7,"name": 0x2f,"type":2},{"bits":5,"name": "xd","type":4},{"bits":3,"name": 0x0,"type":2},{"bits":5,"name": "xs1","type":4},{"bits":5,"name": "xs2","type":4},{"bits":7,"name": 0x21,"type":2}]} +.... + +Description:: +Atomically with release ordering: + + * Load the byte at address _xs1_ + * Write the sign-extended value into _xd_ + * OR the least-significant byte of register _xs2_ to the loaded value + * Write the result to the address in _xs1_ + + +Decode Variables:: +[width="100%", cols="1,2", options="header"] +|=== +|Variable Name |Location +|xs2 |$encoding[24:20] +|xs1 |$encoding[19:15] +|xd |$encoding[11:7] +|=== + +Included in:: +[options="autowrap,autowidth"] +|=== +| Extension | Version + +| *Zabha* | ~> 1.0.0 + +|=== + + +[#udb:doc:inst:amoor_d] +== amoor.d + +Synopsis:: +Atomic fetch-and-or doubleword + +Assembly:: +amoor.d xd, xs2, (xs1) + +Encoding:: +[wavedrom, ,svg,subs='attributes',width="100%"] +.... +{"reg":[{"bits":7,"name": 0x2f,"type":2},{"bits":5,"name": "xd","type":4},{"bits":3,"name": 0x3,"type":2},{"bits":5,"name": "xs1","type":4},{"bits":5,"name": "xs2","type":4},{"bits":7,"name": 0x20,"type":2}]} +.... + +Description:: +Atomically: + + * Load the doubleword at address _xs1_ + * Write the loaded value into _xd_ + * OR the value of register _xs2_ to the loaded value + * Write the result to the address in _xs1_ + + +Decode Variables:: +[width="100%", cols="1,2", options="header"] +|=== +|Variable Name |Location +|xs2 |$encoding[24:20] +|xs1 |$encoding[19:15] +|xd |$encoding[11:7] +|=== + +Included in:: +[options="autowrap,autowidth"] +|=== +| Extension | Version + +| *Zaamo* | ~> 1.0.0 + +|=== + + +[#udb:doc:inst:amoor_d_aq] +== amoor.d.aq + +Synopsis:: +Atomic fetch-and-or doubleword (acquire) + +Assembly:: +amoor.d.aq xd, xs2, (xs1) + +Encoding:: +[wavedrom, ,svg,subs='attributes',width="100%"] +.... +{"reg":[{"bits":7,"name": 0x2f,"type":2},{"bits":5,"name": "xd","type":4},{"bits":3,"name": 0x3,"type":2},{"bits":5,"name": "xs1","type":4},{"bits":5,"name": "xs2","type":4},{"bits":7,"name": 0x22,"type":2}]} +.... + +Description:: +Atomically with acquire ordering: + + * Load the doubleword at address _xs1_ + * Write the loaded value into _xd_ + * OR the value of register _xs2_ to the loaded value + * Write the result to the address in _xs1_ + + +Decode Variables:: +[width="100%", cols="1,2", options="header"] +|=== +|Variable Name |Location +|xs2 |$encoding[24:20] +|xs1 |$encoding[19:15] +|xd |$encoding[11:7] +|=== + +Included in:: +[options="autowrap,autowidth"] +|=== +| Extension | Version + +| *Zaamo* | ~> 1.0.0 + +|=== + + +[#udb:doc:inst:amoor_d_aqrl] +== amoor.d.aqrl + +Synopsis:: +Atomic fetch-and-or doubleword (acquire-release) + +Assembly:: +amoor.d.aqrl xd, xs2, (xs1) + +Encoding:: +[wavedrom, ,svg,subs='attributes',width="100%"] +.... +{"reg":[{"bits":7,"name": 0x2f,"type":2},{"bits":5,"name": "xd","type":4},{"bits":3,"name": 0x3,"type":2},{"bits":5,"name": "xs1","type":4},{"bits":5,"name": "xs2","type":4},{"bits":7,"name": 0x23,"type":2}]} +.... + +Description:: +Atomically with acquire and release ordering: + + * Load the doubleword at address _xs1_ + * Write the loaded value into _xd_ + * OR the value of register _xs2_ to the loaded value + * Write the result to the address in _xs1_ + + +Decode Variables:: +[width="100%", cols="1,2", options="header"] +|=== +|Variable Name |Location +|xs2 |$encoding[24:20] +|xs1 |$encoding[19:15] +|xd |$encoding[11:7] +|=== + +Included in:: +[options="autowrap,autowidth"] +|=== +| Extension | Version + +| *Zaamo* | ~> 1.0.0 + +|=== + + +[#udb:doc:inst:amoor_d_rl] +== amoor.d.rl + +Synopsis:: +Atomic fetch-and-or doubleword (release) + +Assembly:: +amoor.d.rl xd, xs2, (xs1) + +Encoding:: +[wavedrom, ,svg,subs='attributes',width="100%"] +.... +{"reg":[{"bits":7,"name": 0x2f,"type":2},{"bits":5,"name": "xd","type":4},{"bits":3,"name": 0x3,"type":2},{"bits":5,"name": "xs1","type":4},{"bits":5,"name": "xs2","type":4},{"bits":7,"name": 0x21,"type":2}]} +.... + +Description:: +Atomically with release ordering: + + * Load the doubleword at address _xs1_ + * Write the loaded value into _xd_ + * OR the value of register _xs2_ to the loaded value + * Write the result to the address in _xs1_ + + +Decode Variables:: +[width="100%", cols="1,2", options="header"] +|=== +|Variable Name |Location +|xs2 |$encoding[24:20] +|xs1 |$encoding[19:15] +|xd |$encoding[11:7] +|=== + +Included in:: +[options="autowrap,autowidth"] +|=== +| Extension | Version + +| *Zaamo* | ~> 1.0.0 + +|=== + + +[#udb:doc:inst:amoor_h] +== amoor.h + +Synopsis:: +Atomic fetch-and-or halfword + +Assembly:: +amoor.h xd, xs2, (xs1) + +Encoding:: +[wavedrom, ,svg,subs='attributes',width="100%"] +.... +{"reg":[{"bits":7,"name": 0x2f,"type":2},{"bits":5,"name": "xd","type":4},{"bits":3,"name": 0x1,"type":2},{"bits":5,"name": "xs1","type":4},{"bits":5,"name": "xs2","type":4},{"bits":7,"name": 0x20,"type":2}]} +.... + +Description:: +Atomically: + + * Load the halfword at address _xs1_ + * Write the sign-extended value into _xd_ + * OR the least-significant halfword of register _xs2_ to the loaded value + * Write the result to the address in _xs1_ + + +Decode Variables:: +[width="100%", cols="1,2", options="header"] +|=== +|Variable Name |Location +|xs2 |$encoding[24:20] +|xs1 |$encoding[19:15] +|xd |$encoding[11:7] +|=== + +Included in:: +[options="autowrap,autowidth"] +|=== +| Extension | Version + +| *Zabha* | ~> 1.0.0 + +|=== + + +[#udb:doc:inst:amoor_h_aq] +== amoor.h.aq + +Synopsis:: +Atomic fetch-and-or halfword (acquire) + +Assembly:: +amoor.h.aq xd, xs2, (xs1) + +Encoding:: +[wavedrom, ,svg,subs='attributes',width="100%"] +.... +{"reg":[{"bits":7,"name": 0x2f,"type":2},{"bits":5,"name": "xd","type":4},{"bits":3,"name": 0x1,"type":2},{"bits":5,"name": "xs1","type":4},{"bits":5,"name": "xs2","type":4},{"bits":7,"name": 0x22,"type":2}]} +.... + +Description:: +Atomically with acquire ordering: + + * Load the halfword at address _xs1_ + * Write the sign-extended value into _xd_ + * OR the least-significant halfword of register _xs2_ to the loaded value + * Write the result to the address in _xs1_ + + +Decode Variables:: +[width="100%", cols="1,2", options="header"] +|=== +|Variable Name |Location +|xs2 |$encoding[24:20] +|xs1 |$encoding[19:15] +|xd |$encoding[11:7] +|=== + +Included in:: +[options="autowrap,autowidth"] +|=== +| Extension | Version + +| *Zabha* | ~> 1.0.0 + +|=== + + +[#udb:doc:inst:amoor_h_aqrl] +== amoor.h.aqrl Synopsis:: -Atomic fetch-and-add word +Atomic fetch-and-or halfword (acquire-release) Assembly:: -amoadd.w xd, xs2, (xs1) +amoor.h.aqrl xd, xs2, (xs1) Encoding:: [wavedrom, ,svg,subs='attributes',width="100%"] .... -{"reg":[{"bits":7,"name": 0x2f,"type":2},{"bits":5,"name": "xd","type":4},{"bits":3,"name": 0x2,"type":2},{"bits":5,"name": "xs1","type":4},{"bits":5,"name": "xs2","type":4},{"bits":1,"name": "rl","type":4},{"bits":1,"name": "aq","type":4},{"bits":5,"name": 0x0,"type":2}]} +{"reg":[{"bits":7,"name": 0x2f,"type":2},{"bits":5,"name": "xd","type":4},{"bits":3,"name": 0x1,"type":2},{"bits":5,"name": "xs1","type":4},{"bits":5,"name": "xs2","type":4},{"bits":7,"name": 0x23,"type":2}]} .... Description:: -Atomically: +Atomically with acquire and release ordering: - * Load the word at address _xs1_ + * Load the halfword at address _xs1_ * Write the sign-extended value into _xd_ - * Add the least-significant word of register _xs2_ to the loaded value - * Write the sum to the address in _xs1_ + * OR the least-significant halfword of register _xs2_ to the loaded value + * Write the result to the address in _xs1_ Decode Variables:: [width="100%", cols="1,2", options="header"] |=== |Variable Name |Location -|aq |$encoding[26] -|rl |$encoding[25] |xs2 |$encoding[24:20] |xs1 |$encoding[19:15] |xd |$encoding[11:7] @@ -801,36 +6092,39 @@ Included in:: |=== | Extension | Version -| *Zaamo* | ~> 1.0.0 +| *Zabha* | ~> 1.0.0 |=== -[#udb:doc:inst:amoand_b] -== amoand.b +[#udb:doc:inst:amoor_h_rl] +== amoor.h.rl Synopsis:: -No synopsis available +Atomic fetch-and-or halfword (release) Assembly:: -amoand.b xd, xs2, (xs1) +amoor.h.rl xd, xs2, (xs1) Encoding:: [wavedrom, ,svg,subs='attributes',width="100%"] .... -{"reg":[{"bits":7,"name": 0x2f,"type":2},{"bits":5,"name": "xd","type":4},{"bits":3,"name": 0x0,"type":2},{"bits":5,"name": "xs1","type":4},{"bits":5,"name": "xs2","type":4},{"bits":1,"name": "rl","type":4},{"bits":1,"name": "aq","type":4},{"bits":5,"name": 0xc,"type":2}]} +{"reg":[{"bits":7,"name": 0x2f,"type":2},{"bits":5,"name": "xd","type":4},{"bits":3,"name": 0x1,"type":2},{"bits":5,"name": "xs1","type":4},{"bits":5,"name": "xs2","type":4},{"bits":7,"name": 0x21,"type":2}]} .... Description:: -No description available. +Atomically with release ordering: + + * Load the halfword at address _xs1_ + * Write the sign-extended value into _xd_ + * OR the least-significant halfword of register _xs2_ to the loaded value + * Write the result to the address in _xs1_ Decode Variables:: [width="100%", cols="1,2", options="header"] |=== |Variable Name |Location -|aq |$encoding[26] -|rl |$encoding[25] |xs2 |$encoding[24:20] |xs1 |$encoding[19:15] |xd |$encoding[11:7] @@ -846,27 +6140,27 @@ Included in:: |=== -[#udb:doc:inst:amoand_d] -== amoand.d +[#udb:doc:inst:amoor_w] +== amoor.w Synopsis:: -Atomic fetch-and-and doubleword +Atomic fetch-and-or word Assembly:: -amoand.d xd, xs2, (xs1) +amoor.w xd, xs2, (xs1) Encoding:: [wavedrom, ,svg,subs='attributes',width="100%"] .... -{"reg":[{"bits":7,"name": 0x2f,"type":2},{"bits":5,"name": "xd","type":4},{"bits":3,"name": 0x3,"type":2},{"bits":5,"name": "xs1","type":4},{"bits":5,"name": "xs2","type":4},{"bits":1,"name": "rl","type":4},{"bits":1,"name": "aq","type":4},{"bits":5,"name": 0xc,"type":2}]} +{"reg":[{"bits":7,"name": 0x2f,"type":2},{"bits":5,"name": "xd","type":4},{"bits":3,"name": 0x2,"type":2},{"bits":5,"name": "xs1","type":4},{"bits":5,"name": "xs2","type":4},{"bits":7,"name": 0x20,"type":2}]} .... Description:: Atomically: - * Load the doubleword at address _xs1_ - * Write the loaded value into _xd_ - * AND the value of register _xs2_ to the loaded value + * Load the word at address _xs1_ + * Write the sign-extended value into _xd_ + * OR the least-significant word of register _xs2_ to the loaded value * Write the result to the address in _xs1_ @@ -874,8 +6168,6 @@ Decode Variables:: [width="100%", cols="1,2", options="header"] |=== |Variable Name |Location -|aq |$encoding[26] -|rl |$encoding[25] |xs2 |$encoding[24:20] |xs1 |$encoding[19:15] |xd |$encoding[11:7] @@ -891,31 +6183,34 @@ Included in:: |=== -[#udb:doc:inst:amoand_h] -== amoand.h +[#udb:doc:inst:amoor_w_aq] +== amoor.w.aq Synopsis:: -No synopsis available +Atomic fetch-and-or word (acquire) Assembly:: -amoand.h xd, xs2, (xs1) +amoor.w.aq xd, xs2, (xs1) Encoding:: [wavedrom, ,svg,subs='attributes',width="100%"] .... -{"reg":[{"bits":7,"name": 0x2f,"type":2},{"bits":5,"name": "xd","type":4},{"bits":3,"name": 0x1,"type":2},{"bits":5,"name": "xs1","type":4},{"bits":5,"name": "xs2","type":4},{"bits":1,"name": "rl","type":4},{"bits":1,"name": "aq","type":4},{"bits":5,"name": 0xc,"type":2}]} +{"reg":[{"bits":7,"name": 0x2f,"type":2},{"bits":5,"name": "xd","type":4},{"bits":3,"name": 0x2,"type":2},{"bits":5,"name": "xs1","type":4},{"bits":5,"name": "xs2","type":4},{"bits":7,"name": 0x22,"type":2}]} .... Description:: -No description available. +Atomically with acquire ordering: + + * Load the word at address _xs1_ + * Write the sign-extended value into _xd_ + * OR the least-significant word of register _xs2_ to the loaded value + * Write the result to the address in _xs1_ Decode Variables:: [width="100%", cols="1,2", options="header"] |=== |Variable Name |Location -|aq |$encoding[26] -|rl |$encoding[25] |xs2 |$encoding[24:20] |xs1 |$encoding[19:15] |xd |$encoding[11:7] @@ -926,32 +6221,32 @@ Included in:: |=== | Extension | Version -| *Zabha* | ~> 1.0.0 +| *Zaamo* | ~> 1.0.0 |=== -[#udb:doc:inst:amoand_w] -== amoand.w +[#udb:doc:inst:amoor_w_aqrl] +== amoor.w.aqrl Synopsis:: -Atomic fetch-and-and word +Atomic fetch-and-or word (acquire-release) Assembly:: -amoand.w xd, xs2, (xs1) +amoor.w.aqrl xd, xs2, (xs1) Encoding:: [wavedrom, ,svg,subs='attributes',width="100%"] .... -{"reg":[{"bits":7,"name": 0x2f,"type":2},{"bits":5,"name": "xd","type":4},{"bits":3,"name": 0x2,"type":2},{"bits":5,"name": "xs1","type":4},{"bits":5,"name": "xs2","type":4},{"bits":1,"name": "rl","type":4},{"bits":1,"name": "aq","type":4},{"bits":5,"name": 0xc,"type":2}]} +{"reg":[{"bits":7,"name": 0x2f,"type":2},{"bits":5,"name": "xd","type":4},{"bits":3,"name": 0x2,"type":2},{"bits":5,"name": "xs1","type":4},{"bits":5,"name": "xs2","type":4},{"bits":7,"name": 0x23,"type":2}]} .... Description:: -Atomically: +Atomically with acquire and release ordering: * Load the word at address _xs1_ * Write the sign-extended value into _xd_ - * AND the least-significant word of register _xs2_ to the loaded value + * OR the least-significant word of register _xs2_ to the loaded value * Write the result to the address in _xs1_ @@ -959,8 +6254,6 @@ Decode Variables:: [width="100%", cols="1,2", options="header"] |=== |Variable Name |Location -|aq |$encoding[26] -|rl |$encoding[25] |xs2 |$encoding[24:20] |xs1 |$encoding[19:15] |xd |$encoding[11:7] @@ -976,31 +6269,34 @@ Included in:: |=== -[#udb:doc:inst:amocas_b] -== amocas.b +[#udb:doc:inst:amoor_w_rl] +== amoor.w.rl Synopsis:: -No synopsis available +Atomic fetch-and-or word (release) Assembly:: -amocas.b xd, xs2, (xs1) +amoor.w.rl xd, xs2, (xs1) Encoding:: [wavedrom, ,svg,subs='attributes',width="100%"] .... -{"reg":[{"bits":7,"name": 0x2f,"type":2},{"bits":5,"name": "xd","type":4},{"bits":3,"name": 0x0,"type":2},{"bits":5,"name": "xs1","type":4},{"bits":5,"name": "xs2","type":4},{"bits":1,"name": "rl","type":4},{"bits":1,"name": "aq","type":4},{"bits":5,"name": 0x5,"type":2}]} +{"reg":[{"bits":7,"name": 0x2f,"type":2},{"bits":5,"name": "xd","type":4},{"bits":3,"name": 0x2,"type":2},{"bits":5,"name": "xs1","type":4},{"bits":5,"name": "xs2","type":4},{"bits":7,"name": 0x21,"type":2}]} .... Description:: -No description available. +Atomically with release ordering: + + * Load the word at address _xs1_ + * Write the sign-extended value into _xd_ + * OR the least-significant word of register _xs2_ to the loaded value + * Write the result to the address in _xs1_ Decode Variables:: [width="100%", cols="1,2", options="header"] |=== |Variable Name |Location -|aq |$encoding[26] -|rl |$encoding[25] |xs2 |$encoding[24:20] |xs1 |$encoding[19:15] |xd |$encoding[11:7] @@ -1011,98 +6307,38 @@ Included in:: |=== | Extension | Version -| *Zabha* | ~> 1.0.0 +| *Zaamo* | ~> 1.0.0 |=== -[#udb:doc:inst:amocas_d] -== amocas.d +[#udb:doc:inst:amoswap_b] +== amoswap.b Synopsis:: -Atomic Compare-and-Swap Doubleword +Atomic SWAP byte Assembly:: -amocas.d xd, xs2, (xs1) +amoswap.b xd, xs2, (xs1) Encoding:: -[NOTE] -This instruction has different encodings in RV32 and RV64 - -RV32:: -[wavedrom, ,svg,subs='attributes',width="100%"] -.... -{"reg":[{"bits":7,"name": 0x2f,"type":2},{"bits":5,"name": "xd != {1,3,5,7,9,11,13,15,17,19,21,23,25,27,29,31}","type":4},{"bits":3,"name": 0x3,"type":2},{"bits":5,"name": "xs1","type":4},{"bits":5,"name": "xs2 != {1,3,5,7,9,11,13,15,17,19,21,23,25,27,29,31}","type":4},{"bits":1,"name": "rl","type":4},{"bits":1,"name": "aq","type":4},{"bits":5,"name": 0x5,"type":2}]} -.... - -RV64:: [wavedrom, ,svg,subs='attributes',width="100%"] .... -{"reg":[{"bits":7,"name": 0x2f,"type":2},{"bits":5,"name": "xd","type":4},{"bits":3,"name": 0x3,"type":2},{"bits":5,"name": "xs1","type":4},{"bits":5,"name": "xs2","type":4},{"bits":1,"name": "rl","type":4},{"bits":1,"name": "aq","type":4},{"bits":5,"name": 0x5,"type":2}]} +{"reg":[{"bits":7,"name": 0x2f,"type":2},{"bits":5,"name": "xd","type":4},{"bits":3,"name": 0x0,"type":2},{"bits":5,"name": "xs1","type":4},{"bits":5,"name": "xs2","type":4},{"bits":7,"name": 0x4,"type":2}]} .... Description:: -For RV32, AMOCAS.D atomically loads 64-bits of a data value from address in -xs1, compares the loaded value to a 64-bit value held in a register pair -consisting of xd and xd+1, and if the comparison is bitwise equal, then -stores the 64-bit value held in the register pair xs2 and xs2+1 to the -original address in xs1. The value loaded from memory is placed into the -register pair xd and xd+1. The instruction requires the first register in -the pair to be even numbered; encodings with odd-numbered registers -specified in xs2 and xd are reserved. When the first register of a source -register pair is x0, then both halves of the pair read as zero. When the -first register of a destination register pair is x0, then the entire -register result is discarded and neither destination register is written. - -For RV64, AMOCAS.D atomically loads 64-bits of a data value from address in -xs1, compares the loaded value to a 64-bit value held in xd, and if the -comparison is bitwise equal, then stores the 64-bit value held in xs2 to the -original address in xs1. The value loaded from memory is placed into -register xd. - -Just as for AMOs in the A extension, AMOCAS.D requires that the address held -in xs1 be naturally aligned to the size of the operand (i.e., eight-byte -aligned for doublewords). And the same exception options apply if the -address is not naturally aligned. - -Just as for AMOs in the A extension, the AMOCAS.D optionally provides release -consistency semantics, using the aq and rl bits, to help implement -multiprocessor synchronization. The memory operation performed by an -AMOCAS.D, when successful, has acquire semantics if aq bit is 1 and has -release semantics if rl bit is 1. The memory operation performed by an -AMOCAS.W/D/Q, when not successful, has acquire semantics if aq bit is 1 but -does not have release semantics, regardless of rl. - -A FENCE instruction may be used to order the memory read access and, if -produced, the memory write access by an AMOCAS.D instruction. - -[Note] An unsuccessful AMOCAS.D may either not perform a memory write or may -write back the old value loaded from memory. The memory write, if produced, -does not have release semantics, regardless of rl. +Atomically: -An AMOCAS.D instruction always requires write permissions. + * Load the byte at address _xs1_ + * Write the sign-extended value into _xd_ + * Store the least-significant byte of register _xs2_ to the address in _xs1_ Decode Variables:: -*RV32:* - -[width="100%", cols="1,2", options="header"] -|=== -|Variable Name |Location -|aq |$encoding[26] -|rl |$encoding[25] -|xs2 |$encoding[24:20] -|xs1 |$encoding[19:15] -|xd |$encoding[11:7] -|=== - -*RV64:* - [width="100%", cols="1,2", options="header"] |=== |Variable Name |Location -|aq |$encoding[26] -|rl |$encoding[25] |xs2 |$encoding[24:20] |xs1 |$encoding[19:15] |xd |$encoding[11:7] @@ -1113,36 +6349,38 @@ Included in:: |=== | Extension | Version -| *Zacas* | ~> 1.0.0 +| *Zabha* | ~> 1.0.0 |=== -[#udb:doc:inst:amocas_h] -== amocas.h +[#udb:doc:inst:amoswap_b_aq] +== amoswap.b.aq Synopsis:: -No synopsis available +Atomic SWAP byte (acquire) Assembly:: -amocas.h xd, xs2, (xs1) +amoswap.b.aq xd, xs2, (xs1) Encoding:: [wavedrom, ,svg,subs='attributes',width="100%"] .... -{"reg":[{"bits":7,"name": 0x2f,"type":2},{"bits":5,"name": "xd","type":4},{"bits":3,"name": 0x1,"type":2},{"bits":5,"name": "xs1","type":4},{"bits":5,"name": "xs2","type":4},{"bits":1,"name": "rl","type":4},{"bits":1,"name": "aq","type":4},{"bits":5,"name": 0x5,"type":2}]} +{"reg":[{"bits":7,"name": 0x2f,"type":2},{"bits":5,"name": "xd","type":4},{"bits":3,"name": 0x0,"type":2},{"bits":5,"name": "xs1","type":4},{"bits":5,"name": "xs2","type":4},{"bits":7,"name": 0x6,"type":2}]} .... Description:: -No description available. +Atomically with acquire ordering: + + * Load the byte at address _xs1_ + * Write the sign-extended value into _xd_ + * Store the least-significant byte of register _xs2_ to the address in _xs1_ Decode Variables:: [width="100%", cols="1,2", options="header"] |=== |Variable Name |Location -|aq |$encoding[26] -|rl |$encoding[25] |xs2 |$encoding[24:20] |xs1 |$encoding[19:15] |xd |$encoding[11:7] @@ -1158,63 +6396,33 @@ Included in:: |=== -[#udb:doc:inst:amocas_q] -== amocas.q +[#udb:doc:inst:amoswap_b_aqrl] +== amoswap.b.aqrl Synopsis:: -Atomic Compare-and-Swap Quadword +Atomic SWAP byte (acquire-release) Assembly:: -amocas.q xd, xs2, (xs1) +amoswap.b.aqrl xd, xs2, (xs1) Encoding:: [wavedrom, ,svg,subs='attributes',width="100%"] .... -{"reg":[{"bits":7,"name": 0x2f,"type":2},{"bits":5,"name": "xd != {1,3,5,7,9,11,13,15,17,19,21,23,25,27,29,31}","type":4},{"bits":3,"name": 0x4,"type":2},{"bits":5,"name": "xs1","type":4},{"bits":5,"name": "xs2 != {1,3,5,7,9,11,13,15,17,19,21,23,25,27,29,31}","type":4},{"bits":1,"name": "rl","type":4},{"bits":1,"name": "aq","type":4},{"bits":5,"name": 0x5,"type":2}]} +{"reg":[{"bits":7,"name": 0x2f,"type":2},{"bits":5,"name": "xd","type":4},{"bits":3,"name": 0x0,"type":2},{"bits":5,"name": "xs1","type":4},{"bits":5,"name": "xs2","type":4},{"bits":7,"name": 0x7,"type":2}]} .... Description:: -For RV64, AMOCAS.Q atomically loads 128-bits of a data value from address -in xs1, compares the loaded value to a 128-bit value held in a register -pair consisting of xd and xd+1, and if the comparison is bitwise equal, -then stores the 128-bit value held in the register pair xs2 and xs2+1 to -the original address in xs1. The value loaded from memory is placed into -the register pair xd and xd+1. The instruction requires the first register -in the pair to be even numbered; encodings with odd-numbered registers -specified in xs2 and xd are reserved. When the first register of a source -register pair is x0, then both halves of the pair read as zero. When the -first register of a destination register pair is x0, then the entire -register result is discarded and neither destination register is written. - -Just as for AMOs in the A extension, AMOCAS.Q requires that the address held -in xs1 be naturally aligned to the size of the operand (i.e., sixteen-byte -aligned for quadwords). And the same exception options apply if the -address is not naturally aligned. - -Just as for AMOs in the A extension, the AMOCAS.Q optionally provides release -consistency semantics, using the aq and rl bits, to help implement -multiprocessor synchronization. The memory operation performed by an -AMOCAS.Q, when successful, has acquire semantics if aq bit is 1 and has -release semantics if rl bit is 1. The memory operation performed by an -AMOCAS.W/D/Q, when not successful, has acquire semantics if aq bit is 1 but -does not have release semantics, regardless of rl. +Atomically with acquire and release ordering: -A FENCE instruction may be used to order the memory read access and, if -produced, the memory write access by an AMOCAS.Q instruction. - -[Note] An unsuccessful AMOCAS.Q may either not perform a memory write or -may write back the old value loaded from memory. The memory write, if -produced, does not have release semantics, regardless of rl. - -An AMOCAS.Q instruction always requires write permissions. + * Load the byte at address _xs1_ + * Write the sign-extended value into _xd_ + * Store the least-significant byte of register _xs2_ to the address in _xs1_ Decode Variables:: [width="100%", cols="1,2", options="header"] |=== |Variable Name |Location -|aq |$encoding[26] -|rl |$encoding[25] |xs2 |$encoding[24:20] |xs1 |$encoding[19:15] |xd |$encoding[11:7] @@ -1225,68 +6433,38 @@ Included in:: |=== | Extension | Version -| *Zacas* | ~> 1.0.0 +| *Zabha* | ~> 1.0.0 |=== -[#udb:doc:inst:amocas_w] -== amocas.w +[#udb:doc:inst:amoswap_b_rl] +== amoswap.b.rl Synopsis:: -Atomic Compare-and-Swap Word +Atomic SWAP byte (release) Assembly:: -amocas.w xd, xs2, (xs1) +amoswap.b.rl xd, xs2, (xs1) Encoding:: [wavedrom, ,svg,subs='attributes',width="100%"] .... -{"reg":[{"bits":7,"name": 0x2f,"type":2},{"bits":5,"name": "xd","type":4},{"bits":3,"name": 0x2,"type":2},{"bits":5,"name": "xs1","type":4},{"bits":5,"name": "xs2","type":4},{"bits":1,"name": "rl","type":4},{"bits":1,"name": "aq","type":4},{"bits":5,"name": 0x5,"type":2}]} +{"reg":[{"bits":7,"name": 0x2f,"type":2},{"bits":5,"name": "xd","type":4},{"bits":3,"name": 0x0,"type":2},{"bits":5,"name": "xs1","type":4},{"bits":5,"name": "xs2","type":4},{"bits":7,"name": 0x5,"type":2}]} .... Description:: -For RV32, AMOCAS.W atomically loads a 32-bit data value from address in xs1, -compares the loaded value to the 32-bit value held in xd, and if the -comparison is bitwise equal, then stores the 32-bit value held in xs2 to the -original address in xs1. The value loaded from memory is placed into -register xd. - -For RV64, AMOCAS.W atomically loads a 32-bit data value from address in xs1, -compares the loaded value to the lower 32 bits of the value held in xd, and -if the comparison is bitwise equal, then stores the lower 32 bits of the -value held in xs2 to the original address in xs1. The 32-bit value loaded -from memory is sign-extended and is placed into register xd. - -Just as for AMOs in the A extension, AMOCAS.W requires that the address held -in xs1 be naturally aligned to the size of the operand (i.e., four-byte -aligned for words). And the same exception options apply if the address is -not naturally aligned. +Atomically with release ordering: -Just as for AMOs in the A extension, the AMOCAS.W optionally provides release -consistency semantics, using the aq and rl bits, to help implement -multiprocessor synchronization. The memory operation performed by an -AMOCAS.W, when successful, has acquire semantics if aq bit is 1 and has -release semantics if rl bit is 1. The memory operation performed by an -AMOCAS.W/D/Q, when not successful, has acquire semantics if aq bit is 1 but -does not have release semantics, regardless of rl. - -A FENCE instruction may be used to order the memory read access and, if -produced, the memory write access by an AMOCAS.W instruction. - -[Note] An unsuccessful AMOCAS.W may either not perform a memory write or may -write back the old value loaded from memory. The memory write, if produced, -does not have release semantics, regardless of rl. - -An AMOCAS.W instruction always requires write permissions. + * Load the byte at address _xs1_ + * Write the sign-extended value into _xd_ + * Store the least-significant byte of register _xs2_ to the address in _xs1_ Decode Variables:: [width="100%", cols="1,2", options="header"] |=== |Variable Name |Location -|aq |$encoding[26] -|rl |$encoding[25] |xs2 |$encoding[24:20] |xs1 |$encoding[19:15] |xd |$encoding[11:7] @@ -1297,36 +6475,38 @@ Included in:: |=== | Extension | Version -| *Zacas* | ~> 1.0.0 +| *Zabha* | ~> 1.0.0 |=== -[#udb:doc:inst:amomax_b] -== amomax.b +[#udb:doc:inst:amoswap_d] +== amoswap.d Synopsis:: -No synopsis available +Atomic SWAP doubleword Assembly:: -amomax.b xd, xs2, (xs1) +amoswap.d xd, xs2, (xs1) Encoding:: [wavedrom, ,svg,subs='attributes',width="100%"] .... -{"reg":[{"bits":7,"name": 0x2f,"type":2},{"bits":5,"name": "xd","type":4},{"bits":3,"name": 0x0,"type":2},{"bits":5,"name": "xs1","type":4},{"bits":5,"name": "xs2","type":4},{"bits":1,"name": "rl","type":4},{"bits":1,"name": "aq","type":4},{"bits":5,"name": 0x14,"type":2}]} +{"reg":[{"bits":7,"name": 0x2f,"type":2},{"bits":5,"name": "xd","type":4},{"bits":3,"name": 0x3,"type":2},{"bits":5,"name": "xs1","type":4},{"bits":5,"name": "xs2","type":4},{"bits":7,"name": 0x4,"type":2}]} .... Description:: -No description available. +Atomically: + + * Load the doubleword at address _xs1_ + * Write the loaded value into _xd_ + * Store the value of register _xs2_ to the address in _xs1_ Decode Variables:: [width="100%", cols="1,2", options="header"] |=== |Variable Name |Location -|aq |$encoding[26] -|rl |$encoding[25] |xs2 |$encoding[24:20] |xs1 |$encoding[19:15] |xd |$encoding[11:7] @@ -1337,41 +6517,38 @@ Included in:: |=== | Extension | Version -| *Zabha* | ~> 1.0.0 +| *Zaamo* | ~> 1.0.0 |=== -[#udb:doc:inst:amomax_d] -== amomax.d +[#udb:doc:inst:amoswap_d_aq] +== amoswap.d.aq Synopsis:: -Atomic MAX doubleword +Atomic SWAP doubleword (acquire) Assembly:: -amomax.d xd, xs2, (xs1) +amoswap.d.aq xd, xs2, (xs1) Encoding:: [wavedrom, ,svg,subs='attributes',width="100%"] .... -{"reg":[{"bits":7,"name": 0x2f,"type":2},{"bits":5,"name": "xd","type":4},{"bits":3,"name": 0x3,"type":2},{"bits":5,"name": "xs1","type":4},{"bits":5,"name": "xs2","type":4},{"bits":1,"name": "rl","type":4},{"bits":1,"name": "aq","type":4},{"bits":5,"name": 0x14,"type":2}]} +{"reg":[{"bits":7,"name": 0x2f,"type":2},{"bits":5,"name": "xd","type":4},{"bits":3,"name": 0x3,"type":2},{"bits":5,"name": "xs1","type":4},{"bits":5,"name": "xs2","type":4},{"bits":7,"name": 0x6,"type":2}]} .... Description:: -Atomically: +Atomically with acquire ordering: * Load the doubleword at address _xs1_ * Write the loaded value into _xd_ - * Signed compare the value of register _xs2_ to the loaded value, and select the maximum value - * Write the maximum to the address in _xs1_ + * Store the value of register _xs2_ to the address in _xs1_ Decode Variables:: [width="100%", cols="1,2", options="header"] |=== |Variable Name |Location -|aq |$encoding[26] -|rl |$encoding[25] |xs2 |$encoding[24:20] |xs1 |$encoding[19:15] |xd |$encoding[11:7] @@ -1387,31 +6564,33 @@ Included in:: |=== -[#udb:doc:inst:amomax_h] -== amomax.h +[#udb:doc:inst:amoswap_d_aqrl] +== amoswap.d.aqrl Synopsis:: -No synopsis available +Atomic SWAP doubleword (acquire-release) Assembly:: -amomax.h xd, xs2, (xs1) +amoswap.d.aqrl xd, xs2, (xs1) Encoding:: [wavedrom, ,svg,subs='attributes',width="100%"] .... -{"reg":[{"bits":7,"name": 0x2f,"type":2},{"bits":5,"name": "xd","type":4},{"bits":3,"name": 0x1,"type":2},{"bits":5,"name": "xs1","type":4},{"bits":5,"name": "xs2","type":4},{"bits":1,"name": "rl","type":4},{"bits":1,"name": "aq","type":4},{"bits":5,"name": 0x14,"type":2}]} +{"reg":[{"bits":7,"name": 0x2f,"type":2},{"bits":5,"name": "xd","type":4},{"bits":3,"name": 0x3,"type":2},{"bits":5,"name": "xs1","type":4},{"bits":5,"name": "xs2","type":4},{"bits":7,"name": 0x7,"type":2}]} .... Description:: -No description available. +Atomically with acquire and release ordering: + + * Load the doubleword at address _xs1_ + * Write the loaded value into _xd_ + * Store the value of register _xs2_ to the address in _xs1_ Decode Variables:: [width="100%", cols="1,2", options="header"] |=== |Variable Name |Location -|aq |$encoding[26] -|rl |$encoding[25] |xs2 |$encoding[24:20] |xs1 |$encoding[19:15] |xd |$encoding[11:7] @@ -1422,41 +6601,38 @@ Included in:: |=== | Extension | Version -| *Zabha* | ~> 1.0.0 +| *Zaamo* | ~> 1.0.0 |=== -[#udb:doc:inst:amomax_w] -== amomax.w +[#udb:doc:inst:amoswap_d_rl] +== amoswap.d.rl Synopsis:: -Atomic MAX word +Atomic SWAP doubleword (release) Assembly:: -amomax.w xd, xs2, (xs1) +amoswap.d.rl xd, xs2, (xs1) Encoding:: [wavedrom, ,svg,subs='attributes',width="100%"] .... -{"reg":[{"bits":7,"name": 0x2f,"type":2},{"bits":5,"name": "xd","type":4},{"bits":3,"name": 0x2,"type":2},{"bits":5,"name": "xs1","type":4},{"bits":5,"name": "xs2","type":4},{"bits":1,"name": "rl","type":4},{"bits":1,"name": "aq","type":4},{"bits":5,"name": 0x14,"type":2}]} +{"reg":[{"bits":7,"name": 0x2f,"type":2},{"bits":5,"name": "xd","type":4},{"bits":3,"name": 0x3,"type":2},{"bits":5,"name": "xs1","type":4},{"bits":5,"name": "xs2","type":4},{"bits":7,"name": 0x5,"type":2}]} .... Description:: -Atomically: +Atomically with release ordering: - * Load the word at address _xs1_ - * Write the sign-extended value into _xd_ - * Signed compare the least-significant word of register _xs2_ to the loaded value, and select the maximum value - * Write the maximum to the address in _xs1_ + * Load the doubleword at address _xs1_ + * Write the loaded value into _xd_ + * Store the value of register _xs2_ to the address in _xs1_ Decode Variables:: [width="100%", cols="1,2", options="header"] |=== |Variable Name |Location -|aq |$encoding[26] -|rl |$encoding[25] |xs2 |$encoding[24:20] |xs1 |$encoding[19:15] |xd |$encoding[11:7] @@ -1472,31 +6648,33 @@ Included in:: |=== -[#udb:doc:inst:amomaxu_b] -== amomaxu.b +[#udb:doc:inst:amoswap_h] +== amoswap.h Synopsis:: -No synopsis available +Atomic SWAP halfword Assembly:: -amomaxu.b xd, xs2, (xs1) +amoswap.h xd, xs2, (xs1) Encoding:: [wavedrom, ,svg,subs='attributes',width="100%"] .... -{"reg":[{"bits":7,"name": 0x2f,"type":2},{"bits":5,"name": "xd","type":4},{"bits":3,"name": 0x0,"type":2},{"bits":5,"name": "xs1","type":4},{"bits":5,"name": "xs2","type":4},{"bits":1,"name": "rl","type":4},{"bits":1,"name": "aq","type":4},{"bits":5,"name": 0x1c,"type":2}]} +{"reg":[{"bits":7,"name": 0x2f,"type":2},{"bits":5,"name": "xd","type":4},{"bits":3,"name": 0x1,"type":2},{"bits":5,"name": "xs1","type":4},{"bits":5,"name": "xs2","type":4},{"bits":7,"name": 0x4,"type":2}]} .... Description:: -No description available. +Atomically: + + * Load the halfword at address _xs1_ + * Write the sign-extended value into _xd_ + * Store the least-significant halfword of register _xs2_ to the address in _xs1_ Decode Variables:: [width="100%", cols="1,2", options="header"] |=== |Variable Name |Location -|aq |$encoding[26] -|rl |$encoding[25] |xs2 |$encoding[24:20] |xs1 |$encoding[19:15] |xd |$encoding[11:7] @@ -1512,36 +6690,33 @@ Included in:: |=== -[#udb:doc:inst:amomaxu_d] -== amomaxu.d +[#udb:doc:inst:amoswap_h_aq] +== amoswap.h.aq Synopsis:: -Atomic MAX unsigned doubleword +Atomic SWAP halfword (acquire) Assembly:: -amomaxu.d xd, xs2, (xs1) +amoswap.h.aq xd, xs2, (xs1) Encoding:: [wavedrom, ,svg,subs='attributes',width="100%"] .... -{"reg":[{"bits":7,"name": 0x2f,"type":2},{"bits":5,"name": "xd","type":4},{"bits":3,"name": 0x3,"type":2},{"bits":5,"name": "xs1","type":4},{"bits":5,"name": "xs2","type":4},{"bits":1,"name": "rl","type":4},{"bits":1,"name": "aq","type":4},{"bits":5,"name": 0x1c,"type":2}]} +{"reg":[{"bits":7,"name": 0x2f,"type":2},{"bits":5,"name": "xd","type":4},{"bits":3,"name": 0x1,"type":2},{"bits":5,"name": "xs1","type":4},{"bits":5,"name": "xs2","type":4},{"bits":7,"name": 0x6,"type":2}]} .... Description:: -Atomically: +Atomically with acquire ordering: - * Load the doubleword at address _xs1_ - * Write the loaded value into _xd_ - * Unsigned compare the value of register _xs2_ to the loaded value, and select the maximum value - * Write the maximum to the address in _xs1_ + * Load the halfword at address _xs1_ + * Write the sign-extended value into _xd_ + * Store the least-significant halfword of register _xs2_ to the address in _xs1_ Decode Variables:: [width="100%", cols="1,2", options="header"] |=== |Variable Name |Location -|aq |$encoding[26] -|rl |$encoding[25] |xs2 |$encoding[24:20] |xs1 |$encoding[19:15] |xd |$encoding[11:7] @@ -1552,36 +6727,38 @@ Included in:: |=== | Extension | Version -| *Zaamo* | ~> 1.0.0 +| *Zabha* | ~> 1.0.0 |=== -[#udb:doc:inst:amomaxu_h] -== amomaxu.h +[#udb:doc:inst:amoswap_h_aqrl] +== amoswap.h.aqrl Synopsis:: -No synopsis available +Atomic SWAP halfword (acquire-release) Assembly:: -amomaxu.h xd, xs2, (xs1) +amoswap.h.aqrl xd, xs2, (xs1) Encoding:: [wavedrom, ,svg,subs='attributes',width="100%"] .... -{"reg":[{"bits":7,"name": 0x2f,"type":2},{"bits":5,"name": "xd","type":4},{"bits":3,"name": 0x1,"type":2},{"bits":5,"name": "xs1","type":4},{"bits":5,"name": "xs2","type":4},{"bits":1,"name": "rl","type":4},{"bits":1,"name": "aq","type":4},{"bits":5,"name": 0x1c,"type":2}]} +{"reg":[{"bits":7,"name": 0x2f,"type":2},{"bits":5,"name": "xd","type":4},{"bits":3,"name": 0x1,"type":2},{"bits":5,"name": "xs1","type":4},{"bits":5,"name": "xs2","type":4},{"bits":7,"name": 0x7,"type":2}]} .... Description:: -No description available. +Atomically with acquire and release ordering: + + * Load the halfword at address _xs1_ + * Write the sign-extended value into _xd_ + * Store the least-significant halfword of register _xs2_ to the address in _xs1_ Decode Variables:: [width="100%", cols="1,2", options="header"] |=== |Variable Name |Location -|aq |$encoding[26] -|rl |$encoding[25] |xs2 |$encoding[24:20] |xs1 |$encoding[19:15] |xd |$encoding[11:7] @@ -1597,36 +6774,33 @@ Included in:: |=== -[#udb:doc:inst:amomaxu_w] -== amomaxu.w +[#udb:doc:inst:amoswap_h_rl] +== amoswap.h.rl Synopsis:: -Atomic MAX unsigned word +Atomic SWAP halfword (release) Assembly:: -amomaxu.w xd, xs2, (xs1) +amoswap.h.rl xd, xs2, (xs1) Encoding:: [wavedrom, ,svg,subs='attributes',width="100%"] .... -{"reg":[{"bits":7,"name": 0x2f,"type":2},{"bits":5,"name": "xd","type":4},{"bits":3,"name": 0x2,"type":2},{"bits":5,"name": "xs1","type":4},{"bits":5,"name": "xs2","type":4},{"bits":1,"name": "rl","type":4},{"bits":1,"name": "aq","type":4},{"bits":5,"name": 0x1c,"type":2}]} +{"reg":[{"bits":7,"name": 0x2f,"type":2},{"bits":5,"name": "xd","type":4},{"bits":3,"name": 0x1,"type":2},{"bits":5,"name": "xs1","type":4},{"bits":5,"name": "xs2","type":4},{"bits":7,"name": 0x5,"type":2}]} .... Description:: -Atomically: +Atomically with release ordering: - * Load the word at address _xs1_ + * Load the halfword at address _xs1_ * Write the sign-extended value into _xd_ - * Unsigned compare the least-significant word of register _xs2_ to the loaded value, and select the maximum value - * Write the maximum to the address in _xs1_ + * Store the least-significant halfword of register _xs2_ to the address in _xs1_ Decode Variables:: [width="100%", cols="1,2", options="header"] |=== |Variable Name |Location -|aq |$encoding[26] -|rl |$encoding[25] |xs2 |$encoding[24:20] |xs1 |$encoding[19:15] |xd |$encoding[11:7] @@ -1637,36 +6811,38 @@ Included in:: |=== | Extension | Version -| *Zaamo* | ~> 1.0.0 +| *Zabha* | ~> 1.0.0 |=== -[#udb:doc:inst:amomin_b] -== amomin.b +[#udb:doc:inst:amoswap_w] +== amoswap.w Synopsis:: -No synopsis available +Atomic SWAP word Assembly:: -amomin.b xd, xs2, (xs1) +amoswap.w xd, xs2, (xs1) Encoding:: [wavedrom, ,svg,subs='attributes',width="100%"] .... -{"reg":[{"bits":7,"name": 0x2f,"type":2},{"bits":5,"name": "xd","type":4},{"bits":3,"name": 0x0,"type":2},{"bits":5,"name": "xs1","type":4},{"bits":5,"name": "xs2","type":4},{"bits":1,"name": "rl","type":4},{"bits":1,"name": "aq","type":4},{"bits":5,"name": 0x10,"type":2}]} +{"reg":[{"bits":7,"name": 0x2f,"type":2},{"bits":5,"name": "xd","type":4},{"bits":3,"name": 0x2,"type":2},{"bits":5,"name": "xs1","type":4},{"bits":5,"name": "xs2","type":4},{"bits":7,"name": 0x4,"type":2}]} .... Description:: -No description available. +Atomically: + + * Load the word at address _xs1_ + * Write the sign-extended value into _xd_ + * Store the least-significant word of register _xs2_ to the address in _xs1_ Decode Variables:: [width="100%", cols="1,2", options="header"] |=== |Variable Name |Location -|aq |$encoding[26] -|rl |$encoding[25] |xs2 |$encoding[24:20] |xs1 |$encoding[19:15] |xd |$encoding[11:7] @@ -1677,41 +6853,38 @@ Included in:: |=== | Extension | Version -| *Zabha* | ~> 1.0.0 +| *Zaamo* | ~> 1.0.0 |=== -[#udb:doc:inst:amomin_d] -== amomin.d +[#udb:doc:inst:amoswap_w_aq] +== amoswap.w.aq Synopsis:: -Atomic MIN doubleword +Atomic SWAP word (acquire) Assembly:: -amomin.d xd, xs2, (xs1) +amoswap.w.aq xd, xs2, (xs1) Encoding:: [wavedrom, ,svg,subs='attributes',width="100%"] .... -{"reg":[{"bits":7,"name": 0x2f,"type":2},{"bits":5,"name": "xd","type":4},{"bits":3,"name": 0x3,"type":2},{"bits":5,"name": "xs1","type":4},{"bits":5,"name": "xs2","type":4},{"bits":1,"name": "rl","type":4},{"bits":1,"name": "aq","type":4},{"bits":5,"name": 0x10,"type":2}]} +{"reg":[{"bits":7,"name": 0x2f,"type":2},{"bits":5,"name": "xd","type":4},{"bits":3,"name": 0x2,"type":2},{"bits":5,"name": "xs1","type":4},{"bits":5,"name": "xs2","type":4},{"bits":7,"name": 0x6,"type":2}]} .... Description:: -Atomically: +Atomically with acquire ordering: - * Load the doubleword at address _xs1_ - * Write the loaded value into _xd_ - * Signed compare the value of register _xs2_ to the loaded value, and select the minimum value - * Write the minimum to the address in _xs1_ + * Load the word at address _xs1_ + * Write the sign-extended value into _xd_ + * Store the least-significant word of register _xs2_ to the address in _xs1_ Decode Variables:: [width="100%", cols="1,2", options="header"] |=== |Variable Name |Location -|aq |$encoding[26] -|rl |$encoding[25] |xs2 |$encoding[24:20] |xs1 |$encoding[19:15] |xd |$encoding[11:7] @@ -1727,31 +6900,33 @@ Included in:: |=== -[#udb:doc:inst:amomin_h] -== amomin.h +[#udb:doc:inst:amoswap_w_aqrl] +== amoswap.w.aqrl Synopsis:: -No synopsis available +Atomic SWAP word (acquire-release) Assembly:: -amomin.h xd, xs2, (xs1) +amoswap.w.aqrl xd, xs2, (xs1) Encoding:: [wavedrom, ,svg,subs='attributes',width="100%"] .... -{"reg":[{"bits":7,"name": 0x2f,"type":2},{"bits":5,"name": "xd","type":4},{"bits":3,"name": 0x1,"type":2},{"bits":5,"name": "xs1","type":4},{"bits":5,"name": "xs2","type":4},{"bits":1,"name": "rl","type":4},{"bits":1,"name": "aq","type":4},{"bits":5,"name": 0x10,"type":2}]} +{"reg":[{"bits":7,"name": 0x2f,"type":2},{"bits":5,"name": "xd","type":4},{"bits":3,"name": 0x2,"type":2},{"bits":5,"name": "xs1","type":4},{"bits":5,"name": "xs2","type":4},{"bits":7,"name": 0x7,"type":2}]} .... Description:: -No description available. +Atomically with acquire and release ordering: + + * Load the word at address _xs1_ + * Write the sign-extended value into _xd_ + * Store the least-significant word of register _xs2_ to the address in _xs1_ Decode Variables:: [width="100%", cols="1,2", options="header"] |=== |Variable Name |Location -|aq |$encoding[26] -|rl |$encoding[25] |xs2 |$encoding[24:20] |xs1 |$encoding[19:15] |xd |$encoding[11:7] @@ -1762,41 +6937,38 @@ Included in:: |=== | Extension | Version -| *Zabha* | ~> 1.0.0 +| *Zaamo* | ~> 1.0.0 |=== -[#udb:doc:inst:amomin_w] -== amomin.w +[#udb:doc:inst:amoswap_w_rl] +== amoswap.w.rl Synopsis:: -Atomic MIN word +Atomic SWAP word (release) Assembly:: -amomin.w xd, xs2, (xs1) +amoswap.w.rl xd, xs2, (xs1) Encoding:: [wavedrom, ,svg,subs='attributes',width="100%"] .... -{"reg":[{"bits":7,"name": 0x2f,"type":2},{"bits":5,"name": "xd","type":4},{"bits":3,"name": 0x2,"type":2},{"bits":5,"name": "xs1","type":4},{"bits":5,"name": "xs2","type":4},{"bits":1,"name": "rl","type":4},{"bits":1,"name": "aq","type":4},{"bits":5,"name": 0x10,"type":2}]} +{"reg":[{"bits":7,"name": 0x2f,"type":2},{"bits":5,"name": "xd","type":4},{"bits":3,"name": 0x2,"type":2},{"bits":5,"name": "xs1","type":4},{"bits":5,"name": "xs2","type":4},{"bits":7,"name": 0x5,"type":2}]} .... Description:: -Atomically: +Atomically with release ordering: * Load the word at address _xs1_ * Write the sign-extended value into _xd_ - * Signed compare the least-significant word of register _xs2_ to the loaded value, and select the minimum value - * Write the result to the address in _xs1_ + * Store the least-significant word of register _xs2_ to the address in _xs1_ Decode Variables:: [width="100%", cols="1,2", options="header"] |=== |Variable Name |Location -|aq |$encoding[26] -|rl |$encoding[25] |xs2 |$encoding[24:20] |xs1 |$encoding[19:15] |xd |$encoding[11:7] @@ -1812,31 +6984,34 @@ Included in:: |=== -[#udb:doc:inst:amominu_b] -== amominu.b +[#udb:doc:inst:amoxor_b] +== amoxor.b Synopsis:: -No synopsis available +Atomic fetch-and-xor byte Assembly:: -amominu.b xd, xs2, (xs1) +amoxor.b xd, xs2, (xs1) Encoding:: [wavedrom, ,svg,subs='attributes',width="100%"] .... -{"reg":[{"bits":7,"name": 0x2f,"type":2},{"bits":5,"name": "xd","type":4},{"bits":3,"name": 0x0,"type":2},{"bits":5,"name": "xs1","type":4},{"bits":5,"name": "xs2","type":4},{"bits":1,"name": "rl","type":4},{"bits":1,"name": "aq","type":4},{"bits":5,"name": 0x18,"type":2}]} +{"reg":[{"bits":7,"name": 0x2f,"type":2},{"bits":5,"name": "xd","type":4},{"bits":3,"name": 0x0,"type":2},{"bits":5,"name": "xs1","type":4},{"bits":5,"name": "xs2","type":4},{"bits":7,"name": 0x10,"type":2}]} .... Description:: -No description available. +Atomically: + + * Load the byte at address _xs1_ + * Write the sign-extended value into _xd_ + * XOR the least-significant byte of register _xs2_ to the loaded value + * Write the result to the address in _xs1_ Decode Variables:: [width="100%", cols="1,2", options="header"] |=== |Variable Name |Location -|aq |$encoding[26] -|rl |$encoding[25] |xs2 |$encoding[24:20] |xs1 |$encoding[19:15] |xd |$encoding[11:7] @@ -1852,36 +7027,34 @@ Included in:: |=== -[#udb:doc:inst:amominu_d] -== amominu.d +[#udb:doc:inst:amoxor_b_aq] +== amoxor.b.aq Synopsis:: -Atomic MIN unsigned doubleword +Atomic fetch-and-xor byte (acquire) Assembly:: -amominu.d xd, xs2, (xs1) +amoxor.b.aq xd, xs2, (xs1) Encoding:: [wavedrom, ,svg,subs='attributes',width="100%"] .... -{"reg":[{"bits":7,"name": 0x2f,"type":2},{"bits":5,"name": "xd","type":4},{"bits":3,"name": 0x3,"type":2},{"bits":5,"name": "xs1","type":4},{"bits":5,"name": "xs2","type":4},{"bits":1,"name": "rl","type":4},{"bits":1,"name": "aq","type":4},{"bits":5,"name": 0x18,"type":2}]} +{"reg":[{"bits":7,"name": 0x2f,"type":2},{"bits":5,"name": "xd","type":4},{"bits":3,"name": 0x0,"type":2},{"bits":5,"name": "xs1","type":4},{"bits":5,"name": "xs2","type":4},{"bits":7,"name": 0x12,"type":2}]} .... Description:: -Atomically: +Atomically with acquire ordering: - * Load the doubleword at address _xs1_ - * Write the loaded value into _xd_ - * Unsigned compare the value of register _xs2_ to the loaded value, and select the minimum value - * Write the minimum to the address in _xs1_ + * Load the byte at address _xs1_ + * Write the sign-extended value into _xd_ + * XOR the least-significant byte of register _xs2_ to the loaded value + * Write the result to the address in _xs1_ Decode Variables:: [width="100%", cols="1,2", options="header"] |=== |Variable Name |Location -|aq |$encoding[26] -|rl |$encoding[25] |xs2 |$encoding[24:20] |xs1 |$encoding[19:15] |xd |$encoding[11:7] @@ -1892,36 +7065,39 @@ Included in:: |=== | Extension | Version -| *Zaamo* | ~> 1.0.0 +| *Zabha* | ~> 1.0.0 |=== -[#udb:doc:inst:amominu_h] -== amominu.h +[#udb:doc:inst:amoxor_b_aqrl] +== amoxor.b.aqrl Synopsis:: -No synopsis available +Atomic fetch-and-xor byte (acquire-release) Assembly:: -amominu.h xd, xs2, (xs1) +amoxor.b.aqrl xd, xs2, (xs1) Encoding:: [wavedrom, ,svg,subs='attributes',width="100%"] .... -{"reg":[{"bits":7,"name": 0x2f,"type":2},{"bits":5,"name": "xd","type":4},{"bits":3,"name": 0x1,"type":2},{"bits":5,"name": "xs1","type":4},{"bits":5,"name": "xs2","type":4},{"bits":1,"name": "rl","type":4},{"bits":1,"name": "aq","type":4},{"bits":5,"name": 0x18,"type":2}]} +{"reg":[{"bits":7,"name": 0x2f,"type":2},{"bits":5,"name": "xd","type":4},{"bits":3,"name": 0x0,"type":2},{"bits":5,"name": "xs1","type":4},{"bits":5,"name": "xs2","type":4},{"bits":7,"name": 0x13,"type":2}]} .... Description:: -No description available. +Atomically with acquire and release ordering: + + * Load the byte at address _xs1_ + * Write the sign-extended value into _xd_ + * XOR the least-significant byte of register _xs2_ to the loaded value + * Write the result to the address in _xs1_ Decode Variables:: [width="100%", cols="1,2", options="header"] |=== |Variable Name |Location -|aq |$encoding[26] -|rl |$encoding[25] |xs2 |$encoding[24:20] |xs1 |$encoding[19:15] |xd |$encoding[11:7] @@ -1937,27 +7113,27 @@ Included in:: |=== -[#udb:doc:inst:amominu_w] -== amominu.w +[#udb:doc:inst:amoxor_b_rl] +== amoxor.b.rl Synopsis:: -Atomic MIN unsigned word +Atomic fetch-and-xor byte (release) Assembly:: -amominu.w xd, xs2, (xs1) +amoxor.b.rl xd, xs2, (xs1) Encoding:: [wavedrom, ,svg,subs='attributes',width="100%"] .... -{"reg":[{"bits":7,"name": 0x2f,"type":2},{"bits":5,"name": "xd","type":4},{"bits":3,"name": 0x2,"type":2},{"bits":5,"name": "xs1","type":4},{"bits":5,"name": "xs2","type":4},{"bits":1,"name": "rl","type":4},{"bits":1,"name": "aq","type":4},{"bits":5,"name": 0x18,"type":2}]} +{"reg":[{"bits":7,"name": 0x2f,"type":2},{"bits":5,"name": "xd","type":4},{"bits":3,"name": 0x0,"type":2},{"bits":5,"name": "xs1","type":4},{"bits":5,"name": "xs2","type":4},{"bits":7,"name": 0x11,"type":2}]} .... Description:: -Atomically: +Atomically with release ordering: - * Load the word at address _xs1_ + * Load the byte at address _xs1_ * Write the sign-extended value into _xd_ - * Unsigned compare the least-significant word of register _xs2_ to the loaded word, and select the minimum value + * XOR the least-significant byte of register _xs2_ to the loaded value * Write the result to the address in _xs1_ @@ -1965,8 +7141,6 @@ Decode Variables:: [width="100%", cols="1,2", options="header"] |=== |Variable Name |Location -|aq |$encoding[26] -|rl |$encoding[25] |xs2 |$encoding[24:20] |xs1 |$encoding[19:15] |xd |$encoding[11:7] @@ -1977,36 +7151,39 @@ Included in:: |=== | Extension | Version -| *Zaamo* | ~> 1.0.0 +| *Zabha* | ~> 1.0.0 |=== -[#udb:doc:inst:amoor_b] -== amoor.b +[#udb:doc:inst:amoxor_d] +== amoxor.d Synopsis:: -No synopsis available +Atomic fetch-and-xor doubleword Assembly:: -amoor.b xd, xs2, (xs1) +amoxor.d xd, xs2, (xs1) Encoding:: [wavedrom, ,svg,subs='attributes',width="100%"] .... -{"reg":[{"bits":7,"name": 0x2f,"type":2},{"bits":5,"name": "xd","type":4},{"bits":3,"name": 0x0,"type":2},{"bits":5,"name": "xs1","type":4},{"bits":5,"name": "xs2","type":4},{"bits":1,"name": "rl","type":4},{"bits":1,"name": "aq","type":4},{"bits":5,"name": 0x8,"type":2}]} +{"reg":[{"bits":7,"name": 0x2f,"type":2},{"bits":5,"name": "xd","type":4},{"bits":3,"name": 0x3,"type":2},{"bits":5,"name": "xs1","type":4},{"bits":5,"name": "xs2","type":4},{"bits":7,"name": 0x10,"type":2}]} .... Description:: -No description available. +Atomically: + + * Load the doubleword at address _xs1_ + * Write the loaded value into _xd_ + * XOR the value of register _xs2_ to the loaded value + * Write the result to the address in _xs1_ Decode Variables:: [width="100%", cols="1,2", options="header"] |=== |Variable Name |Location -|aq |$encoding[26] -|rl |$encoding[25] |xs2 |$encoding[24:20] |xs1 |$encoding[19:15] |xd |$encoding[11:7] @@ -2017,32 +7194,32 @@ Included in:: |=== | Extension | Version -| *Zabha* | ~> 1.0.0 +| *Zaamo* | ~> 1.0.0 |=== -[#udb:doc:inst:amoor_d] -== amoor.d +[#udb:doc:inst:amoxor_d_aq] +== amoxor.d.aq Synopsis:: -Atomic fetch-and-or doubleword +Atomic fetch-and-xor doubleword (acquire) Assembly:: -amoor.d xd, xs2, (xs1) +amoxor.d.aq xd, xs2, (xs1) Encoding:: [wavedrom, ,svg,subs='attributes',width="100%"] .... -{"reg":[{"bits":7,"name": 0x2f,"type":2},{"bits":5,"name": "xd","type":4},{"bits":3,"name": 0x3,"type":2},{"bits":5,"name": "xs1","type":4},{"bits":5,"name": "xs2","type":4},{"bits":1,"name": "rl","type":4},{"bits":1,"name": "aq","type":4},{"bits":5,"name": 0x8,"type":2}]} +{"reg":[{"bits":7,"name": 0x2f,"type":2},{"bits":5,"name": "xd","type":4},{"bits":3,"name": 0x3,"type":2},{"bits":5,"name": "xs1","type":4},{"bits":5,"name": "xs2","type":4},{"bits":7,"name": 0x12,"type":2}]} .... Description:: -Atomically: +Atomically with acquire ordering: * Load the doubleword at address _xs1_ * Write the loaded value into _xd_ - * OR the value of register _xs2_ to the loaded value + * XOR the value of register _xs2_ to the loaded value * Write the result to the address in _xs1_ @@ -2050,8 +7227,6 @@ Decode Variables:: [width="100%", cols="1,2", options="header"] |=== |Variable Name |Location -|aq |$encoding[26] -|rl |$encoding[25] |xs2 |$encoding[24:20] |xs1 |$encoding[19:15] |xd |$encoding[11:7] @@ -2067,31 +7242,34 @@ Included in:: |=== -[#udb:doc:inst:amoor_h] -== amoor.h +[#udb:doc:inst:amoxor_d_aqrl] +== amoxor.d.aqrl Synopsis:: -No synopsis available +Atomic fetch-and-xor doubleword (acquire-release) Assembly:: -amoor.h xd, xs2, (xs1) +amoxor.d.aqrl xd, xs2, (xs1) Encoding:: [wavedrom, ,svg,subs='attributes',width="100%"] .... -{"reg":[{"bits":7,"name": 0x2f,"type":2},{"bits":5,"name": "xd","type":4},{"bits":3,"name": 0x1,"type":2},{"bits":5,"name": "xs1","type":4},{"bits":5,"name": "xs2","type":4},{"bits":1,"name": "rl","type":4},{"bits":1,"name": "aq","type":4},{"bits":5,"name": 0x8,"type":2}]} +{"reg":[{"bits":7,"name": 0x2f,"type":2},{"bits":5,"name": "xd","type":4},{"bits":3,"name": 0x3,"type":2},{"bits":5,"name": "xs1","type":4},{"bits":5,"name": "xs2","type":4},{"bits":7,"name": 0x13,"type":2}]} .... Description:: -No description available. +Atomically with acquire and release ordering: + + * Load the doubleword at address _xs1_ + * Write the loaded value into _xd_ + * XOR the value of register _xs2_ to the loaded value + * Write the result to the address in _xs1_ Decode Variables:: [width="100%", cols="1,2", options="header"] |=== |Variable Name |Location -|aq |$encoding[26] -|rl |$encoding[25] |xs2 |$encoding[24:20] |xs1 |$encoding[19:15] |xd |$encoding[11:7] @@ -2102,32 +7280,32 @@ Included in:: |=== | Extension | Version -| *Zabha* | ~> 1.0.0 +| *Zaamo* | ~> 1.0.0 |=== -[#udb:doc:inst:amoor_w] -== amoor.w +[#udb:doc:inst:amoxor_d_rl] +== amoxor.d.rl Synopsis:: -Atomic fetch-and-or word +Atomic fetch-and-xor doubleword (release) Assembly:: -amoor.w xd, xs2, (xs1) +amoxor.d.rl xd, xs2, (xs1) Encoding:: [wavedrom, ,svg,subs='attributes',width="100%"] .... -{"reg":[{"bits":7,"name": 0x2f,"type":2},{"bits":5,"name": "xd","type":4},{"bits":3,"name": 0x2,"type":2},{"bits":5,"name": "xs1","type":4},{"bits":5,"name": "xs2","type":4},{"bits":1,"name": "rl","type":4},{"bits":1,"name": "aq","type":4},{"bits":5,"name": 0x8,"type":2}]} +{"reg":[{"bits":7,"name": 0x2f,"type":2},{"bits":5,"name": "xd","type":4},{"bits":3,"name": 0x3,"type":2},{"bits":5,"name": "xs1","type":4},{"bits":5,"name": "xs2","type":4},{"bits":7,"name": 0x11,"type":2}]} .... Description:: -Atomically: +Atomically with release ordering: - * Load the word at address _xs1_ - * Write the sign-extended value into _xd_ - * OR the least-significant word of register _xs2_ to the loaded value + * Load the doubleword at address _xs1_ + * Write the loaded value into _xd_ + * XOR the value of register _xs2_ to the loaded value * Write the result to the address in _xs1_ @@ -2135,8 +7313,6 @@ Decode Variables:: [width="100%", cols="1,2", options="header"] |=== |Variable Name |Location -|aq |$encoding[26] -|rl |$encoding[25] |xs2 |$encoding[24:20] |xs1 |$encoding[19:15] |xd |$encoding[11:7] @@ -2152,31 +7328,34 @@ Included in:: |=== -[#udb:doc:inst:amoswap_b] -== amoswap.b +[#udb:doc:inst:amoxor_h] +== amoxor.h Synopsis:: -No synopsis available +Atomic fetch-and-xor halfword Assembly:: -amoswap.b xd, xs2, (xs1) +amoxor.h xd, xs2, (xs1) Encoding:: [wavedrom, ,svg,subs='attributes',width="100%"] .... -{"reg":[{"bits":7,"name": 0x2f,"type":2},{"bits":5,"name": "xd","type":4},{"bits":3,"name": 0x0,"type":2},{"bits":5,"name": "xs1","type":4},{"bits":5,"name": "xs2","type":4},{"bits":1,"name": "rl","type":4},{"bits":1,"name": "aq","type":4},{"bits":5,"name": 0x1,"type":2}]} +{"reg":[{"bits":7,"name": 0x2f,"type":2},{"bits":5,"name": "xd","type":4},{"bits":3,"name": 0x1,"type":2},{"bits":5,"name": "xs1","type":4},{"bits":5,"name": "xs2","type":4},{"bits":7,"name": 0x10,"type":2}]} .... Description:: -No description available. +Atomically: + + * Load the halfword at address _xs1_ + * Write the sign-extended value into _xd_ + * XOR the least-significant halfword of register _xs2_ to the loaded value + * Write the result to the address in _xs1_ Decode Variables:: [width="100%", cols="1,2", options="header"] |=== |Variable Name |Location -|aq |$encoding[26] -|rl |$encoding[25] |xs2 |$encoding[24:20] |xs1 |$encoding[19:15] |xd |$encoding[11:7] @@ -2192,35 +7371,34 @@ Included in:: |=== -[#udb:doc:inst:amoswap_d] -== amoswap.d +[#udb:doc:inst:amoxor_h_aq] +== amoxor.h.aq Synopsis:: -Atomic SWAP doubleword +Atomic fetch-and-xor halfword (acquire) Assembly:: -amoswap.d xd, xs2, (xs1) +amoxor.h.aq xd, xs2, (xs1) Encoding:: [wavedrom, ,svg,subs='attributes',width="100%"] .... -{"reg":[{"bits":7,"name": 0x2f,"type":2},{"bits":5,"name": "xd","type":4},{"bits":3,"name": 0x3,"type":2},{"bits":5,"name": "xs1","type":4},{"bits":5,"name": "xs2","type":4},{"bits":1,"name": "rl","type":4},{"bits":1,"name": "aq","type":4},{"bits":5,"name": 0x1,"type":2}]} +{"reg":[{"bits":7,"name": 0x2f,"type":2},{"bits":5,"name": "xd","type":4},{"bits":3,"name": 0x1,"type":2},{"bits":5,"name": "xs1","type":4},{"bits":5,"name": "xs2","type":4},{"bits":7,"name": 0x12,"type":2}]} .... Description:: -Atomically: +Atomically with acquire ordering: - * Load the doubleword at address _xs1_ - * Write the value into _xd_ - * Store the value of register _xs2_ to the address in _xs1_ + * Load the halfword at address _xs1_ + * Write the sign-extended value into _xd_ + * XOR the least-significant halfword of register _xs2_ to the loaded value + * Write the result to the address in _xs1_ Decode Variables:: [width="100%", cols="1,2", options="header"] |=== |Variable Name |Location -|aq |$encoding[26] -|rl |$encoding[25] |xs2 |$encoding[24:20] |xs1 |$encoding[19:15] |xd |$encoding[11:7] @@ -2231,36 +7409,39 @@ Included in:: |=== | Extension | Version -| *Zaamo* | ~> 1.0.0 +| *Zabha* | ~> 1.0.0 |=== -[#udb:doc:inst:amoswap_h] -== amoswap.h +[#udb:doc:inst:amoxor_h_aqrl] +== amoxor.h.aqrl Synopsis:: -No synopsis available +Atomic fetch-and-xor halfword (acquire-release) Assembly:: -amoswap.h xd, xs2, (xs1) +amoxor.h.aqrl xd, xs2, (xs1) Encoding:: [wavedrom, ,svg,subs='attributes',width="100%"] .... -{"reg":[{"bits":7,"name": 0x2f,"type":2},{"bits":5,"name": "xd","type":4},{"bits":3,"name": 0x1,"type":2},{"bits":5,"name": "xs1","type":4},{"bits":5,"name": "xs2","type":4},{"bits":1,"name": "rl","type":4},{"bits":1,"name": "aq","type":4},{"bits":5,"name": 0x1,"type":2}]} +{"reg":[{"bits":7,"name": 0x2f,"type":2},{"bits":5,"name": "xd","type":4},{"bits":3,"name": 0x1,"type":2},{"bits":5,"name": "xs1","type":4},{"bits":5,"name": "xs2","type":4},{"bits":7,"name": 0x13,"type":2}]} .... Description:: -No description available. +Atomically with acquire and release ordering: + + * Load the halfword at address _xs1_ + * Write the sign-extended value into _xd_ + * XOR the least-significant halfword of register _xs2_ to the loaded value + * Write the result to the address in _xs1_ Decode Variables:: [width="100%", cols="1,2", options="header"] |=== |Variable Name |Location -|aq |$encoding[26] -|rl |$encoding[25] |xs2 |$encoding[24:20] |xs1 |$encoding[19:15] |xd |$encoding[11:7] @@ -2276,35 +7457,34 @@ Included in:: |=== -[#udb:doc:inst:amoswap_w] -== amoswap.w +[#udb:doc:inst:amoxor_h_rl] +== amoxor.h.rl Synopsis:: -Atomic SWAP word +Atomic fetch-and-xor halfword (release) Assembly:: -amoswap.w xd, xs2, (xs1) +amoxor.h.rl xd, xs2, (xs1) Encoding:: [wavedrom, ,svg,subs='attributes',width="100%"] .... -{"reg":[{"bits":7,"name": 0x2f,"type":2},{"bits":5,"name": "xd","type":4},{"bits":3,"name": 0x2,"type":2},{"bits":5,"name": "xs1","type":4},{"bits":5,"name": "xs2","type":4},{"bits":1,"name": "rl","type":4},{"bits":1,"name": "aq","type":4},{"bits":5,"name": 0x1,"type":2}]} +{"reg":[{"bits":7,"name": 0x2f,"type":2},{"bits":5,"name": "xd","type":4},{"bits":3,"name": 0x1,"type":2},{"bits":5,"name": "xs1","type":4},{"bits":5,"name": "xs2","type":4},{"bits":7,"name": 0x11,"type":2}]} .... Description:: -Atomically: +Atomically with release ordering: - * Load the word at address _xs1_ + * Load the halfword at address _xs1_ * Write the sign-extended value into _xd_ - * Store the least-significant word of register _xs2_ to the address in _xs1_ + * XOR the least-significant halfword of register _xs2_ to the loaded value + * Write the result to the address in _xs1_ Decode Variables:: [width="100%", cols="1,2", options="header"] |=== |Variable Name |Location -|aq |$encoding[26] -|rl |$encoding[25] |xs2 |$encoding[24:20] |xs1 |$encoding[19:15] |xd |$encoding[11:7] @@ -2315,36 +7495,39 @@ Included in:: |=== | Extension | Version -| *Zaamo* | ~> 1.0.0 +| *Zabha* | ~> 1.0.0 |=== -[#udb:doc:inst:amoxor_b] -== amoxor.b +[#udb:doc:inst:amoxor_w] +== amoxor.w Synopsis:: -No synopsis available +Atomic fetch-and-xor word Assembly:: -amoxor.b xd, xs2, (xs1) +amoxor.w xd, xs2, (xs1) Encoding:: [wavedrom, ,svg,subs='attributes',width="100%"] .... -{"reg":[{"bits":7,"name": 0x2f,"type":2},{"bits":5,"name": "xd","type":4},{"bits":3,"name": 0x0,"type":2},{"bits":5,"name": "xs1","type":4},{"bits":5,"name": "xs2","type":4},{"bits":1,"name": "rl","type":4},{"bits":1,"name": "aq","type":4},{"bits":5,"name": 0x4,"type":2}]} +{"reg":[{"bits":7,"name": 0x2f,"type":2},{"bits":5,"name": "xd","type":4},{"bits":3,"name": 0x2,"type":2},{"bits":5,"name": "xs1","type":4},{"bits":5,"name": "xs2","type":4},{"bits":7,"name": 0x10,"type":2}]} .... Description:: -No description available. +Atomically: + + * Load the word at address _xs1_ + * Write the sign-extended value into _xd_ + * XOR the least-significant word of register _xs2_ to the loaded value + * Write the result to the address in _xs1_ Decode Variables:: [width="100%", cols="1,2", options="header"] |=== |Variable Name |Location -|aq |$encoding[26] -|rl |$encoding[25] |xs2 |$encoding[24:20] |xs1 |$encoding[19:15] |xd |$encoding[11:7] @@ -2355,32 +7538,32 @@ Included in:: |=== | Extension | Version -| *Zabha* | ~> 1.0.0 +| *Zaamo* | ~> 1.0.0 |=== -[#udb:doc:inst:amoxor_d] -== amoxor.d +[#udb:doc:inst:amoxor_w_aq] +== amoxor.w.aq Synopsis:: -Atomic fetch-and-xor doubleword +Atomic fetch-and-xor word (acquire) Assembly:: -amoxor.d xd, xs2, (xs1) +amoxor.w.aq xd, xs2, (xs1) Encoding:: [wavedrom, ,svg,subs='attributes',width="100%"] .... -{"reg":[{"bits":7,"name": 0x2f,"type":2},{"bits":5,"name": "xd","type":4},{"bits":3,"name": 0x3,"type":2},{"bits":5,"name": "xs1","type":4},{"bits":5,"name": "xs2","type":4},{"bits":1,"name": "rl","type":4},{"bits":1,"name": "aq","type":4},{"bits":5,"name": 0x4,"type":2}]} +{"reg":[{"bits":7,"name": 0x2f,"type":2},{"bits":5,"name": "xd","type":4},{"bits":3,"name": 0x2,"type":2},{"bits":5,"name": "xs1","type":4},{"bits":5,"name": "xs2","type":4},{"bits":7,"name": 0x12,"type":2}]} .... Description:: -Atomically: +Atomically with acquire ordering: - * Load the doubleword at address _xs1_ - * Write the loaded value into _xd_ - * XOR the value of register _xs2_ to the loaded value + * Load the word at address _xs1_ + * Write the sign-extended value into _xd_ + * XOR the least-significant word of register _xs2_ to the loaded value * Write the result to the address in _xs1_ @@ -2388,8 +7571,6 @@ Decode Variables:: [width="100%", cols="1,2", options="header"] |=== |Variable Name |Location -|aq |$encoding[26] -|rl |$encoding[25] |xs2 |$encoding[24:20] |xs1 |$encoding[19:15] |xd |$encoding[11:7] @@ -2405,31 +7586,34 @@ Included in:: |=== -[#udb:doc:inst:amoxor_h] -== amoxor.h +[#udb:doc:inst:amoxor_w_aqrl] +== amoxor.w.aqrl Synopsis:: -No synopsis available +Atomic fetch-and-xor word (acquire-release) Assembly:: -amoxor.h xd, xs2, (xs1) +amoxor.w.aqrl xd, xs2, (xs1) Encoding:: [wavedrom, ,svg,subs='attributes',width="100%"] .... -{"reg":[{"bits":7,"name": 0x2f,"type":2},{"bits":5,"name": "xd","type":4},{"bits":3,"name": 0x1,"type":2},{"bits":5,"name": "xs1","type":4},{"bits":5,"name": "xs2","type":4},{"bits":1,"name": "rl","type":4},{"bits":1,"name": "aq","type":4},{"bits":5,"name": 0x4,"type":2}]} +{"reg":[{"bits":7,"name": 0x2f,"type":2},{"bits":5,"name": "xd","type":4},{"bits":3,"name": 0x2,"type":2},{"bits":5,"name": "xs1","type":4},{"bits":5,"name": "xs2","type":4},{"bits":7,"name": 0x13,"type":2}]} .... Description:: -No description available. +Atomically with acquire and release ordering: + + * Load the word at address _xs1_ + * Write the sign-extended value into _xd_ + * XOR the least-significant word of register _xs2_ to the loaded value + * Write the result to the address in _xs1_ Decode Variables:: [width="100%", cols="1,2", options="header"] |=== |Variable Name |Location -|aq |$encoding[26] -|rl |$encoding[25] |xs2 |$encoding[24:20] |xs1 |$encoding[19:15] |xd |$encoding[11:7] @@ -2440,28 +7624,28 @@ Included in:: |=== | Extension | Version -| *Zabha* | ~> 1.0.0 +| *Zaamo* | ~> 1.0.0 |=== -[#udb:doc:inst:amoxor_w] -== amoxor.w +[#udb:doc:inst:amoxor_w_rl] +== amoxor.w.rl Synopsis:: -Atomic fetch-and-xor word +Atomic fetch-and-xor word (release) Assembly:: -amoxor.w xd, xs2, (xs1) +amoxor.w.rl xd, xs2, (xs1) Encoding:: [wavedrom, ,svg,subs='attributes',width="100%"] .... -{"reg":[{"bits":7,"name": 0x2f,"type":2},{"bits":5,"name": "xd","type":4},{"bits":3,"name": 0x2,"type":2},{"bits":5,"name": "xs1","type":4},{"bits":5,"name": "xs2","type":4},{"bits":1,"name": "rl","type":4},{"bits":1,"name": "aq","type":4},{"bits":5,"name": 0x4,"type":2}]} +{"reg":[{"bits":7,"name": 0x2f,"type":2},{"bits":5,"name": "xd","type":4},{"bits":3,"name": 0x2,"type":2},{"bits":5,"name": "xs1","type":4},{"bits":5,"name": "xs2","type":4},{"bits":7,"name": 0x11,"type":2}]} .... Description:: -Atomically: +Atomically with release ordering: * Load the word at address _xs1_ * Write the sign-extended value into _xd_ @@ -2473,8 +7657,6 @@ Decode Variables:: [width="100%", cols="1,2", options="header"] |=== |Variable Name |Location -|aq |$encoding[26] -|rl |$encoding[25] |xs2 |$encoding[24:20] |xs1 |$encoding[19:15] |xd |$encoding[11:7] diff --git a/spec/std/isa/inst/Zaamo/amoadd.SIZE.AQRL.layout b/spec/std/isa/inst/Zaamo/amoadd.SIZE.AQRL.layout new file mode 100644 index 0000000000..0a980051df --- /dev/null +++ b/spec/std/isa/inst/Zaamo/amoadd.SIZE.AQRL.layout @@ -0,0 +1,175 @@ +# Copyright (c) Qualcomm Technologies, Inc. and/or its subsidiaries. +# Copyright (c) Abhijit Das(Sukuna0007Abhi) +# SPDX-License-Identifier: BSD-3-Clause-Clear + +# yaml-language-server: $schema=../../../../schemas/inst_schema.json +<%- + raise "'size' must be defined as 'b', 'h', 'w', or 'd'" unless %w[b h w d].include?(size) + raise "'aq' must be defined as true or false" unless [true, false].include?(aq) + raise "'rl' must be defined as true or false" unless [true, false].include?(rl) + + size_info = { + "b" => { name: "byte", bits: 8, funct3: "000", operation_bits: "8" }, + "h" => { name: "halfword", bits: 16, funct3: "001", operation_bits: "16" }, + "w" => { name: "word", bits: 32, funct3: "010", operation_bits: "32" }, + "d" => { name: "doubleword", bits: 64, funct3: "011", operation_bits: "64" } + } + + current_size = size_info[size] + + # Generate instruction name suffix based on aq/rl + aq_rl_suffix = "" + if aq && rl + aq_rl_suffix = ".aqrl" + elsif aq + aq_rl_suffix = ".aq" + elsif rl + aq_rl_suffix = ".rl" + end + + # Generate match string with fixed aq/rl bits + aq_bit = aq ? "1" : "0" + rl_bit = rl ? "1" : "0" +-%> + +$schema: "inst_schema.json#" +kind: instruction +name: amoadd.<%= size %><%= aq_rl_suffix %> +long_name: Atomic fetch-and-add <%= current_size[:name] %><%= aq && rl ? " (acquire-release)" : (aq ? " (acquire)" : (rl ? " (release)" : "")) %> +description: | + Atomically<%= aq && rl ? " with acquire and release ordering" : (aq ? " with acquire ordering" : (rl ? " with release ordering" : "")) %>: + + * Load the <%= current_size[:name] %> at address _xs1_ + * Write the <%= %w[b h w].include?(size) ? "sign-extended value" : "loaded value" %> into _xd_ + * Add the <%= %w[b h w].include?(size) ? "least-significant #{current_size[:name]} of register" : "value of register" %> _xs2_ to the loaded value + * Write the result to the address in _xs1_ +definedBy: <%= %w[b h].include?(size) ? "Zabha" : "Zaamo" %> +<%- if size == "d" -%> +base: 64 +<%- end -%> +assembly: xd, xs2, (xs1) +encoding: + match: 00000<%= aq_bit %><%= rl_bit %>----------<%= current_size[:funct3] %>-----0101111 + variables: + - name: xs2 + location: 24-20 + - name: xs1 + location: 19-15 + - name: xd + location: 11-7 +access: + s: always + u: always + vs: always + vu: always +operation(): | + if (!implemented?(ExtensionName::A) || (MISA_CSR_IMPLEMENTED && (CSR[misa].A == 1'b0))) { + raise (ExceptionCode::IllegalInstruction, mode(), $encoding); + } + +<% if aq -%> + memory_model_acquire(); + +<% end -%> + XReg virtual_address = X[xs1]; + X[xd] = amo<<%= current_size[:operation_bits] %>>(virtual_address, X[xs2]<%= %w[b h w].include?(size) ? "[#{current_size[:bits]-1}:0]" : "" %>, AmoOperation::Add, <%= aq ? "1'b1" : "1'b0" %>, <%= rl ? "1'b1" : "1'b0" %>, $encoding); +<% if rl -%> + + memory_model_release(); +<% end -%> + +# SPDX-SnippetBegin +# SPDX-FileCopyrightText: 2017-2025 Contributors to the RISCV Sail Model +# SPDX-License-Identifier: BSD-2-Clause +sail(): | + { + if extension("A") then { + /* Get the address, X(rs1) (no offset). + * Some extensions perform additional checks on address validity. + */ + match ext_data_get_addr(rs1, zeros(), ReadWrite(Data, Data), width) { + Ext_DataAddr_Error(e) => { ext_handle_data_check_error(e); RETIRE_FAIL }, + Ext_DataAddr_OK(vaddr) => { + match translateAddr(vaddr, ReadWrite(Data, Data)) { + TR_Failure(e, _) => { handle_mem_exception(vaddr, e); RETIRE_FAIL }, + TR_Address(addr, _) => { + let eares : MemoryOpResult(unit) = match (width, sizeof(xlen)) { + (BYTE, _) => mem_write_ea(addr, 1, aq & rl, rl, true), + (HALF, _) => mem_write_ea(addr, 2, aq & rl, rl, true), + (WORD, _) => mem_write_ea(addr, 4, aq & rl, rl, true), + (DOUBLE, 64) => mem_write_ea(addr, 8, aq & rl, rl, true), + _ => internal_error(__FILE__, __LINE__, "Unexpected AMO width") + }; + let is_unsigned : bool = match op { + AMOMINU => true, + AMOMAXU => true, + _ => false + }; + let rs2_val : xlenbits = match width { + BYTE => if is_unsigned then zero_extend(X(rs2)[7..0]) else sign_extend(X(rs2)[7..0]), + HALF => if is_unsigned then zero_extend(X(rs2)[15..0]) else sign_extend(X(rs2)[15..0]), + WORD => if is_unsigned then zero_extend(X(rs2)[31..0]) else sign_extend(X(rs2)[31..0]), + DOUBLE => X(rs2) + }; + match (eares) { + MemException(e) => { handle_mem_exception(vaddr, e); RETIRE_FAIL }, + MemValue(_) => { + let mval : MemoryOpResult(xlenbits) = match (width, sizeof(xlen)) { + (BYTE, _) => extend_value(is_unsigned, mem_read(ReadWrite(Data, Data), addr, 1, aq, aq & rl, true)), + (HALF, _) => extend_value(is_unsigned, mem_read(ReadWrite(Data, Data), addr, 2, aq, aq & rl, true)), + (WORD, _) => extend_value(is_unsigned, mem_read(ReadWrite(Data, Data), addr, 4, aq, aq & rl, true)), + (DOUBLE, 64) => extend_value(is_unsigned, mem_read(ReadWrite(Data, Data), addr, 8, aq, aq & rl, true)), + _ => internal_error(__FILE__, __LINE__, "Unexpected AMO width") + }; + match (mval) { + MemException(e) => { handle_mem_exception(vaddr, e); RETIRE_FAIL }, + MemValue(loaded) => { + let result : xlenbits = + match op { + AMOSWAP => rs2_val, + AMOADD => rs2_val + loaded, + AMOXOR => rs2_val ^ loaded, + AMOAND => rs2_val & loaded, + AMOOR => rs2_val | loaded, + + /* These operations convert bitvectors to integer values using [un]signed, + * and back using to_bits(). + */ + AMOMIN => to_bits(sizeof(xlen), min(signed(rs2_val), signed(loaded))), + AMOMAX => to_bits(sizeof(xlen), max(signed(rs2_val), signed(loaded))), + AMOMINU => to_bits(sizeof(xlen), min(unsigned(rs2_val), unsigned(loaded))), + AMOMAXU => to_bits(sizeof(xlen), max(unsigned(rs2_val), unsigned(loaded))) + }; + let rval : xlenbits = match width { + BYTE => sign_extend(loaded[7..0]), + HALF => sign_extend(loaded[15..0]), + WORD => sign_extend(loaded[31..0]), + DOUBLE => loaded + }; + let wval : MemoryOpResult(bool) = match (width, sizeof(xlen)) { + (BYTE, _) => mem_write_value(addr, 1, result[7..0], aq & rl, rl, true), + (HALF, _) => mem_write_value(addr, 2, result[15..0], aq & rl, rl, true), + (WORD, _) => mem_write_value(addr, 4, result[31..0], aq & rl, rl, true), + (DOUBLE, 64) => mem_write_value(addr, 8, result, aq & rl, rl, true), + _ => internal_error(__FILE__, __LINE__, "Unexpected AMO width") + }; + match (wval) { + MemValue(true) => { X(rd) = rval; RETIRE_SUCCESS }, + MemValue(false) => { internal_error(__FILE__, __LINE__, "AMO got false from mem_write_value") }, + MemException(e) => { handle_mem_exception(vaddr, e); RETIRE_FAIL } + } + } + } + } + } + } + } + } + } + } else { + handle_illegal(); + RETIRE_FAIL + } + } + +# SPDX-SnippetEnd diff --git a/spec/std/isa/inst/Zaamo/amoadd.d.aq.yaml b/spec/std/isa/inst/Zaamo/amoadd.d.aq.yaml new file mode 100644 index 0000000000..20d99e2a68 --- /dev/null +++ b/spec/std/isa/inst/Zaamo/amoadd.d.aq.yaml @@ -0,0 +1,140 @@ +# Copyright (c) Qualcomm Technologies, Inc. and/or its subsidiaries. + +# WARNING: This file is auto-generated from spec/std/isa/inst/Zaamo/amoadd.SIZE.AQRL.layout# Copyright (c) Abhijit Das(Sukuna0007Abhi) +# SPDX-License-Identifier: BSD-3-Clause-Clear + +# yaml-language-server: $schema=../../../../schemas/inst_schema.json + +$schema: "inst_schema.json#" +kind: instruction +name: amoadd.d.aq +long_name: Atomic fetch-and-add doubleword (acquire) +description: | + Atomically with acquire ordering: + + * Load the doubleword at address _xs1_ + * Write the loaded value into _xd_ + * Add the value of register _xs2_ to the loaded value + * Write the result to the address in _xs1_ +definedBy: Zaamo +base: 64 +assembly: xd, xs2, (xs1) +encoding: + match: 0000010----------011-----0101111 + variables: + - name: xs2 + location: 24-20 + - name: xs1 + location: 19-15 + - name: xd + location: 11-7 +access: + s: always + u: always + vs: always + vu: always +operation(): | + if (!implemented?(ExtensionName::A) || (MISA_CSR_IMPLEMENTED && (CSR[misa].A == 1'b0))) { + raise (ExceptionCode::IllegalInstruction, mode(), $encoding); + } + + memory_model_acquire(); + + XReg virtual_address = X[xs1]; + X[xd] = amo<64>(virtual_address, X[xs2], AmoOperation::Add, 1'b1, 1'b0, $encoding); + +# SPDX-SnippetBegin +# SPDX-FileCopyrightText: 2017-2025 Contributors to the RISCV Sail Model +# SPDX-License-Identifier: BSD-2-Clause +sail(): | + { + if extension("A") then { + /* Get the address, X(rs1) (no offset). + * Some extensions perform additional checks on address validity. + */ + match ext_data_get_addr(rs1, zeros(), ReadWrite(Data, Data), width) { + Ext_DataAddr_Error(e) => { ext_handle_data_check_error(e); RETIRE_FAIL }, + Ext_DataAddr_OK(vaddr) => { + match translateAddr(vaddr, ReadWrite(Data, Data)) { + TR_Failure(e, _) => { handle_mem_exception(vaddr, e); RETIRE_FAIL }, + TR_Address(addr, _) => { + let eares : MemoryOpResult(unit) = match (width, sizeof(xlen)) { + (BYTE, _) => mem_write_ea(addr, 1, aq & rl, rl, true), + (HALF, _) => mem_write_ea(addr, 2, aq & rl, rl, true), + (WORD, _) => mem_write_ea(addr, 4, aq & rl, rl, true), + (DOUBLE, 64) => mem_write_ea(addr, 8, aq & rl, rl, true), + _ => internal_error(__FILE__, __LINE__, "Unexpected AMO width") + }; + let is_unsigned : bool = match op { + AMOMINU => true, + AMOMAXU => true, + _ => false + }; + let rs2_val : xlenbits = match width { + BYTE => if is_unsigned then zero_extend(X(rs2)[7..0]) else sign_extend(X(rs2)[7..0]), + HALF => if is_unsigned then zero_extend(X(rs2)[15..0]) else sign_extend(X(rs2)[15..0]), + WORD => if is_unsigned then zero_extend(X(rs2)[31..0]) else sign_extend(X(rs2)[31..0]), + DOUBLE => X(rs2) + }; + match (eares) { + MemException(e) => { handle_mem_exception(vaddr, e); RETIRE_FAIL }, + MemValue(_) => { + let mval : MemoryOpResult(xlenbits) = match (width, sizeof(xlen)) { + (BYTE, _) => extend_value(is_unsigned, mem_read(ReadWrite(Data, Data), addr, 1, aq, aq & rl, true)), + (HALF, _) => extend_value(is_unsigned, mem_read(ReadWrite(Data, Data), addr, 2, aq, aq & rl, true)), + (WORD, _) => extend_value(is_unsigned, mem_read(ReadWrite(Data, Data), addr, 4, aq, aq & rl, true)), + (DOUBLE, 64) => extend_value(is_unsigned, mem_read(ReadWrite(Data, Data), addr, 8, aq, aq & rl, true)), + _ => internal_error(__FILE__, __LINE__, "Unexpected AMO width") + }; + match (mval) { + MemException(e) => { handle_mem_exception(vaddr, e); RETIRE_FAIL }, + MemValue(loaded) => { + let result : xlenbits = + match op { + AMOSWAP => rs2_val, + AMOADD => rs2_val + loaded, + AMOXOR => rs2_val ^ loaded, + AMOAND => rs2_val & loaded, + AMOOR => rs2_val | loaded, + + /* These operations convert bitvectors to integer values using [un]signed, + * and back using to_bits(). + */ + AMOMIN => to_bits(sizeof(xlen), min(signed(rs2_val), signed(loaded))), + AMOMAX => to_bits(sizeof(xlen), max(signed(rs2_val), signed(loaded))), + AMOMINU => to_bits(sizeof(xlen), min(unsigned(rs2_val), unsigned(loaded))), + AMOMAXU => to_bits(sizeof(xlen), max(unsigned(rs2_val), unsigned(loaded))) + }; + let rval : xlenbits = match width { + BYTE => sign_extend(loaded[7..0]), + HALF => sign_extend(loaded[15..0]), + WORD => sign_extend(loaded[31..0]), + DOUBLE => loaded + }; + let wval : MemoryOpResult(bool) = match (width, sizeof(xlen)) { + (BYTE, _) => mem_write_value(addr, 1, result[7..0], aq & rl, rl, true), + (HALF, _) => mem_write_value(addr, 2, result[15..0], aq & rl, rl, true), + (WORD, _) => mem_write_value(addr, 4, result[31..0], aq & rl, rl, true), + (DOUBLE, 64) => mem_write_value(addr, 8, result, aq & rl, rl, true), + _ => internal_error(__FILE__, __LINE__, "Unexpected AMO width") + }; + match (wval) { + MemValue(true) => { X(rd) = rval; RETIRE_SUCCESS }, + MemValue(false) => { internal_error(__FILE__, __LINE__, "AMO got false from mem_write_value") }, + MemException(e) => { handle_mem_exception(vaddr, e); RETIRE_FAIL } + } + } + } + } + } + } + } + } + } + } else { + handle_illegal(); + RETIRE_FAIL + } + } + +# SPDX-SnippetEnd diff --git a/spec/std/isa/inst/Zaamo/amoadd.d.aqrl.yaml b/spec/std/isa/inst/Zaamo/amoadd.d.aqrl.yaml new file mode 100644 index 0000000000..02b1913d4c --- /dev/null +++ b/spec/std/isa/inst/Zaamo/amoadd.d.aqrl.yaml @@ -0,0 +1,142 @@ +# Copyright (c) Qualcomm Technologies, Inc. and/or its subsidiaries. + +# WARNING: This file is auto-generated from spec/std/isa/inst/Zaamo/amoadd.SIZE.AQRL.layout# Copyright (c) Abhijit Das(Sukuna0007Abhi) +# SPDX-License-Identifier: BSD-3-Clause-Clear + +# yaml-language-server: $schema=../../../../schemas/inst_schema.json + +$schema: "inst_schema.json#" +kind: instruction +name: amoadd.d.aqrl +long_name: Atomic fetch-and-add doubleword (acquire-release) +description: | + Atomically with acquire and release ordering: + + * Load the doubleword at address _xs1_ + * Write the loaded value into _xd_ + * Add the value of register _xs2_ to the loaded value + * Write the result to the address in _xs1_ +definedBy: Zaamo +base: 64 +assembly: xd, xs2, (xs1) +encoding: + match: 0000011----------011-----0101111 + variables: + - name: xs2 + location: 24-20 + - name: xs1 + location: 19-15 + - name: xd + location: 11-7 +access: + s: always + u: always + vs: always + vu: always +operation(): | + if (!implemented?(ExtensionName::A) || (MISA_CSR_IMPLEMENTED && (CSR[misa].A == 1'b0))) { + raise (ExceptionCode::IllegalInstruction, mode(), $encoding); + } + + memory_model_acquire(); + + XReg virtual_address = X[xs1]; + X[xd] = amo<64>(virtual_address, X[xs2], AmoOperation::Add, 1'b1, 1'b1, $encoding); + + memory_model_release(); + +# SPDX-SnippetBegin +# SPDX-FileCopyrightText: 2017-2025 Contributors to the RISCV Sail Model +# SPDX-License-Identifier: BSD-2-Clause +sail(): | + { + if extension("A") then { + /* Get the address, X(rs1) (no offset). + * Some extensions perform additional checks on address validity. + */ + match ext_data_get_addr(rs1, zeros(), ReadWrite(Data, Data), width) { + Ext_DataAddr_Error(e) => { ext_handle_data_check_error(e); RETIRE_FAIL }, + Ext_DataAddr_OK(vaddr) => { + match translateAddr(vaddr, ReadWrite(Data, Data)) { + TR_Failure(e, _) => { handle_mem_exception(vaddr, e); RETIRE_FAIL }, + TR_Address(addr, _) => { + let eares : MemoryOpResult(unit) = match (width, sizeof(xlen)) { + (BYTE, _) => mem_write_ea(addr, 1, aq & rl, rl, true), + (HALF, _) => mem_write_ea(addr, 2, aq & rl, rl, true), + (WORD, _) => mem_write_ea(addr, 4, aq & rl, rl, true), + (DOUBLE, 64) => mem_write_ea(addr, 8, aq & rl, rl, true), + _ => internal_error(__FILE__, __LINE__, "Unexpected AMO width") + }; + let is_unsigned : bool = match op { + AMOMINU => true, + AMOMAXU => true, + _ => false + }; + let rs2_val : xlenbits = match width { + BYTE => if is_unsigned then zero_extend(X(rs2)[7..0]) else sign_extend(X(rs2)[7..0]), + HALF => if is_unsigned then zero_extend(X(rs2)[15..0]) else sign_extend(X(rs2)[15..0]), + WORD => if is_unsigned then zero_extend(X(rs2)[31..0]) else sign_extend(X(rs2)[31..0]), + DOUBLE => X(rs2) + }; + match (eares) { + MemException(e) => { handle_mem_exception(vaddr, e); RETIRE_FAIL }, + MemValue(_) => { + let mval : MemoryOpResult(xlenbits) = match (width, sizeof(xlen)) { + (BYTE, _) => extend_value(is_unsigned, mem_read(ReadWrite(Data, Data), addr, 1, aq, aq & rl, true)), + (HALF, _) => extend_value(is_unsigned, mem_read(ReadWrite(Data, Data), addr, 2, aq, aq & rl, true)), + (WORD, _) => extend_value(is_unsigned, mem_read(ReadWrite(Data, Data), addr, 4, aq, aq & rl, true)), + (DOUBLE, 64) => extend_value(is_unsigned, mem_read(ReadWrite(Data, Data), addr, 8, aq, aq & rl, true)), + _ => internal_error(__FILE__, __LINE__, "Unexpected AMO width") + }; + match (mval) { + MemException(e) => { handle_mem_exception(vaddr, e); RETIRE_FAIL }, + MemValue(loaded) => { + let result : xlenbits = + match op { + AMOSWAP => rs2_val, + AMOADD => rs2_val + loaded, + AMOXOR => rs2_val ^ loaded, + AMOAND => rs2_val & loaded, + AMOOR => rs2_val | loaded, + + /* These operations convert bitvectors to integer values using [un]signed, + * and back using to_bits(). + */ + AMOMIN => to_bits(sizeof(xlen), min(signed(rs2_val), signed(loaded))), + AMOMAX => to_bits(sizeof(xlen), max(signed(rs2_val), signed(loaded))), + AMOMINU => to_bits(sizeof(xlen), min(unsigned(rs2_val), unsigned(loaded))), + AMOMAXU => to_bits(sizeof(xlen), max(unsigned(rs2_val), unsigned(loaded))) + }; + let rval : xlenbits = match width { + BYTE => sign_extend(loaded[7..0]), + HALF => sign_extend(loaded[15..0]), + WORD => sign_extend(loaded[31..0]), + DOUBLE => loaded + }; + let wval : MemoryOpResult(bool) = match (width, sizeof(xlen)) { + (BYTE, _) => mem_write_value(addr, 1, result[7..0], aq & rl, rl, true), + (HALF, _) => mem_write_value(addr, 2, result[15..0], aq & rl, rl, true), + (WORD, _) => mem_write_value(addr, 4, result[31..0], aq & rl, rl, true), + (DOUBLE, 64) => mem_write_value(addr, 8, result, aq & rl, rl, true), + _ => internal_error(__FILE__, __LINE__, "Unexpected AMO width") + }; + match (wval) { + MemValue(true) => { X(rd) = rval; RETIRE_SUCCESS }, + MemValue(false) => { internal_error(__FILE__, __LINE__, "AMO got false from mem_write_value") }, + MemException(e) => { handle_mem_exception(vaddr, e); RETIRE_FAIL } + } + } + } + } + } + } + } + } + } + } else { + handle_illegal(); + RETIRE_FAIL + } + } + +# SPDX-SnippetEnd diff --git a/spec/std/isa/inst/Zaamo/amoadd.d.rl.yaml b/spec/std/isa/inst/Zaamo/amoadd.d.rl.yaml new file mode 100644 index 0000000000..eff0b47f0e --- /dev/null +++ b/spec/std/isa/inst/Zaamo/amoadd.d.rl.yaml @@ -0,0 +1,140 @@ +# Copyright (c) Qualcomm Technologies, Inc. and/or its subsidiaries. + +# WARNING: This file is auto-generated from spec/std/isa/inst/Zaamo/amoadd.SIZE.AQRL.layout# Copyright (c) Abhijit Das(Sukuna0007Abhi) +# SPDX-License-Identifier: BSD-3-Clause-Clear + +# yaml-language-server: $schema=../../../../schemas/inst_schema.json + +$schema: "inst_schema.json#" +kind: instruction +name: amoadd.d.rl +long_name: Atomic fetch-and-add doubleword (release) +description: | + Atomically with release ordering: + + * Load the doubleword at address _xs1_ + * Write the loaded value into _xd_ + * Add the value of register _xs2_ to the loaded value + * Write the result to the address in _xs1_ +definedBy: Zaamo +base: 64 +assembly: xd, xs2, (xs1) +encoding: + match: 0000001----------011-----0101111 + variables: + - name: xs2 + location: 24-20 + - name: xs1 + location: 19-15 + - name: xd + location: 11-7 +access: + s: always + u: always + vs: always + vu: always +operation(): | + if (!implemented?(ExtensionName::A) || (MISA_CSR_IMPLEMENTED && (CSR[misa].A == 1'b0))) { + raise (ExceptionCode::IllegalInstruction, mode(), $encoding); + } + + XReg virtual_address = X[xs1]; + X[xd] = amo<64>(virtual_address, X[xs2], AmoOperation::Add, 1'b0, 1'b1, $encoding); + + memory_model_release(); + +# SPDX-SnippetBegin +# SPDX-FileCopyrightText: 2017-2025 Contributors to the RISCV Sail Model +# SPDX-License-Identifier: BSD-2-Clause +sail(): | + { + if extension("A") then { + /* Get the address, X(rs1) (no offset). + * Some extensions perform additional checks on address validity. + */ + match ext_data_get_addr(rs1, zeros(), ReadWrite(Data, Data), width) { + Ext_DataAddr_Error(e) => { ext_handle_data_check_error(e); RETIRE_FAIL }, + Ext_DataAddr_OK(vaddr) => { + match translateAddr(vaddr, ReadWrite(Data, Data)) { + TR_Failure(e, _) => { handle_mem_exception(vaddr, e); RETIRE_FAIL }, + TR_Address(addr, _) => { + let eares : MemoryOpResult(unit) = match (width, sizeof(xlen)) { + (BYTE, _) => mem_write_ea(addr, 1, aq & rl, rl, true), + (HALF, _) => mem_write_ea(addr, 2, aq & rl, rl, true), + (WORD, _) => mem_write_ea(addr, 4, aq & rl, rl, true), + (DOUBLE, 64) => mem_write_ea(addr, 8, aq & rl, rl, true), + _ => internal_error(__FILE__, __LINE__, "Unexpected AMO width") + }; + let is_unsigned : bool = match op { + AMOMINU => true, + AMOMAXU => true, + _ => false + }; + let rs2_val : xlenbits = match width { + BYTE => if is_unsigned then zero_extend(X(rs2)[7..0]) else sign_extend(X(rs2)[7..0]), + HALF => if is_unsigned then zero_extend(X(rs2)[15..0]) else sign_extend(X(rs2)[15..0]), + WORD => if is_unsigned then zero_extend(X(rs2)[31..0]) else sign_extend(X(rs2)[31..0]), + DOUBLE => X(rs2) + }; + match (eares) { + MemException(e) => { handle_mem_exception(vaddr, e); RETIRE_FAIL }, + MemValue(_) => { + let mval : MemoryOpResult(xlenbits) = match (width, sizeof(xlen)) { + (BYTE, _) => extend_value(is_unsigned, mem_read(ReadWrite(Data, Data), addr, 1, aq, aq & rl, true)), + (HALF, _) => extend_value(is_unsigned, mem_read(ReadWrite(Data, Data), addr, 2, aq, aq & rl, true)), + (WORD, _) => extend_value(is_unsigned, mem_read(ReadWrite(Data, Data), addr, 4, aq, aq & rl, true)), + (DOUBLE, 64) => extend_value(is_unsigned, mem_read(ReadWrite(Data, Data), addr, 8, aq, aq & rl, true)), + _ => internal_error(__FILE__, __LINE__, "Unexpected AMO width") + }; + match (mval) { + MemException(e) => { handle_mem_exception(vaddr, e); RETIRE_FAIL }, + MemValue(loaded) => { + let result : xlenbits = + match op { + AMOSWAP => rs2_val, + AMOADD => rs2_val + loaded, + AMOXOR => rs2_val ^ loaded, + AMOAND => rs2_val & loaded, + AMOOR => rs2_val | loaded, + + /* These operations convert bitvectors to integer values using [un]signed, + * and back using to_bits(). + */ + AMOMIN => to_bits(sizeof(xlen), min(signed(rs2_val), signed(loaded))), + AMOMAX => to_bits(sizeof(xlen), max(signed(rs2_val), signed(loaded))), + AMOMINU => to_bits(sizeof(xlen), min(unsigned(rs2_val), unsigned(loaded))), + AMOMAXU => to_bits(sizeof(xlen), max(unsigned(rs2_val), unsigned(loaded))) + }; + let rval : xlenbits = match width { + BYTE => sign_extend(loaded[7..0]), + HALF => sign_extend(loaded[15..0]), + WORD => sign_extend(loaded[31..0]), + DOUBLE => loaded + }; + let wval : MemoryOpResult(bool) = match (width, sizeof(xlen)) { + (BYTE, _) => mem_write_value(addr, 1, result[7..0], aq & rl, rl, true), + (HALF, _) => mem_write_value(addr, 2, result[15..0], aq & rl, rl, true), + (WORD, _) => mem_write_value(addr, 4, result[31..0], aq & rl, rl, true), + (DOUBLE, 64) => mem_write_value(addr, 8, result, aq & rl, rl, true), + _ => internal_error(__FILE__, __LINE__, "Unexpected AMO width") + }; + match (wval) { + MemValue(true) => { X(rd) = rval; RETIRE_SUCCESS }, + MemValue(false) => { internal_error(__FILE__, __LINE__, "AMO got false from mem_write_value") }, + MemException(e) => { handle_mem_exception(vaddr, e); RETIRE_FAIL } + } + } + } + } + } + } + } + } + } + } else { + handle_illegal(); + RETIRE_FAIL + } + } + +# SPDX-SnippetEnd diff --git a/spec/std/isa/inst/Zaamo/amoadd.d.yaml b/spec/std/isa/inst/Zaamo/amoadd.d.yaml index 61c4266c24..dbe51654c2 100644 --- a/spec/std/isa/inst/Zaamo/amoadd.d.yaml +++ b/spec/std/isa/inst/Zaamo/amoadd.d.yaml @@ -1,4 +1,6 @@ # Copyright (c) Qualcomm Technologies, Inc. and/or its subsidiaries. + +# WARNING: This file is auto-generated from spec/std/isa/inst/Zaamo/amoadd.SIZE.AQRL.layout# Copyright (c) Abhijit Das(Sukuna0007Abhi) # SPDX-License-Identifier: BSD-3-Clause-Clear # yaml-language-server: $schema=../../../../schemas/inst_schema.json @@ -13,17 +15,13 @@ description: | * Load the doubleword at address _xs1_ * Write the loaded value into _xd_ * Add the value of register _xs2_ to the loaded value - * Write the sum to the address in _xs1_ + * Write the result to the address in _xs1_ definedBy: Zaamo base: 64 assembly: xd, xs2, (xs1) encoding: - match: 00000------------011-----0101111 + match: 0000000----------011-----0101111 variables: - - name: aq - location: 26 - - name: rl - location: 25 - name: xs2 location: 24-20 - name: xs1 @@ -36,15 +34,12 @@ access: vs: always vu: always operation(): | - if (implemented?(ExtensionName::A) && (CSR[misa].A == 1'b0)) { - # even though this is a memory operation, the exception occurs before that would be known, - # so mode() is the correct reporting mode rathat than effective_ldst_mode() + if (!implemented?(ExtensionName::A) || (MISA_CSR_IMPLEMENTED && (CSR[misa].A == 1'b0))) { raise (ExceptionCode::IllegalInstruction, mode(), $encoding); } XReg virtual_address = X[xs1]; - - X[xd] = amo<64>(virtual_address, X[xs2], AmoOperation::Add, aq, rl, $encoding); + X[xd] = amo<64>(virtual_address, X[xs2], AmoOperation::Add, 1'b0, 1'b0, $encoding); # SPDX-SnippetBegin # SPDX-FileCopyrightText: 2017-2025 Contributors to the RISCV Sail Model diff --git a/spec/std/isa/inst/Zaamo/amoadd.w.aq.yaml b/spec/std/isa/inst/Zaamo/amoadd.w.aq.yaml new file mode 100644 index 0000000000..3dda6be32a --- /dev/null +++ b/spec/std/isa/inst/Zaamo/amoadd.w.aq.yaml @@ -0,0 +1,139 @@ +# Copyright (c) Qualcomm Technologies, Inc. and/or its subsidiaries. + +# WARNING: This file is auto-generated from spec/std/isa/inst/Zaamo/amoadd.SIZE.AQRL.layout# Copyright (c) Abhijit Das(Sukuna0007Abhi) +# SPDX-License-Identifier: BSD-3-Clause-Clear + +# yaml-language-server: $schema=../../../../schemas/inst_schema.json + +$schema: "inst_schema.json#" +kind: instruction +name: amoadd.w.aq +long_name: Atomic fetch-and-add word (acquire) +description: | + Atomically with acquire ordering: + + * Load the word at address _xs1_ + * Write the sign-extended value into _xd_ + * Add the least-significant word of register _xs2_ to the loaded value + * Write the result to the address in _xs1_ +definedBy: Zaamo +assembly: xd, xs2, (xs1) +encoding: + match: 0000010----------010-----0101111 + variables: + - name: xs2 + location: 24-20 + - name: xs1 + location: 19-15 + - name: xd + location: 11-7 +access: + s: always + u: always + vs: always + vu: always +operation(): | + if (!implemented?(ExtensionName::A) || (MISA_CSR_IMPLEMENTED && (CSR[misa].A == 1'b0))) { + raise (ExceptionCode::IllegalInstruction, mode(), $encoding); + } + + memory_model_acquire(); + + XReg virtual_address = X[xs1]; + X[xd] = amo<32>(virtual_address, X[xs2][31:0], AmoOperation::Add, 1'b1, 1'b0, $encoding); + +# SPDX-SnippetBegin +# SPDX-FileCopyrightText: 2017-2025 Contributors to the RISCV Sail Model +# SPDX-License-Identifier: BSD-2-Clause +sail(): | + { + if extension("A") then { + /* Get the address, X(rs1) (no offset). + * Some extensions perform additional checks on address validity. + */ + match ext_data_get_addr(rs1, zeros(), ReadWrite(Data, Data), width) { + Ext_DataAddr_Error(e) => { ext_handle_data_check_error(e); RETIRE_FAIL }, + Ext_DataAddr_OK(vaddr) => { + match translateAddr(vaddr, ReadWrite(Data, Data)) { + TR_Failure(e, _) => { handle_mem_exception(vaddr, e); RETIRE_FAIL }, + TR_Address(addr, _) => { + let eares : MemoryOpResult(unit) = match (width, sizeof(xlen)) { + (BYTE, _) => mem_write_ea(addr, 1, aq & rl, rl, true), + (HALF, _) => mem_write_ea(addr, 2, aq & rl, rl, true), + (WORD, _) => mem_write_ea(addr, 4, aq & rl, rl, true), + (DOUBLE, 64) => mem_write_ea(addr, 8, aq & rl, rl, true), + _ => internal_error(__FILE__, __LINE__, "Unexpected AMO width") + }; + let is_unsigned : bool = match op { + AMOMINU => true, + AMOMAXU => true, + _ => false + }; + let rs2_val : xlenbits = match width { + BYTE => if is_unsigned then zero_extend(X(rs2)[7..0]) else sign_extend(X(rs2)[7..0]), + HALF => if is_unsigned then zero_extend(X(rs2)[15..0]) else sign_extend(X(rs2)[15..0]), + WORD => if is_unsigned then zero_extend(X(rs2)[31..0]) else sign_extend(X(rs2)[31..0]), + DOUBLE => X(rs2) + }; + match (eares) { + MemException(e) => { handle_mem_exception(vaddr, e); RETIRE_FAIL }, + MemValue(_) => { + let mval : MemoryOpResult(xlenbits) = match (width, sizeof(xlen)) { + (BYTE, _) => extend_value(is_unsigned, mem_read(ReadWrite(Data, Data), addr, 1, aq, aq & rl, true)), + (HALF, _) => extend_value(is_unsigned, mem_read(ReadWrite(Data, Data), addr, 2, aq, aq & rl, true)), + (WORD, _) => extend_value(is_unsigned, mem_read(ReadWrite(Data, Data), addr, 4, aq, aq & rl, true)), + (DOUBLE, 64) => extend_value(is_unsigned, mem_read(ReadWrite(Data, Data), addr, 8, aq, aq & rl, true)), + _ => internal_error(__FILE__, __LINE__, "Unexpected AMO width") + }; + match (mval) { + MemException(e) => { handle_mem_exception(vaddr, e); RETIRE_FAIL }, + MemValue(loaded) => { + let result : xlenbits = + match op { + AMOSWAP => rs2_val, + AMOADD => rs2_val + loaded, + AMOXOR => rs2_val ^ loaded, + AMOAND => rs2_val & loaded, + AMOOR => rs2_val | loaded, + + /* These operations convert bitvectors to integer values using [un]signed, + * and back using to_bits(). + */ + AMOMIN => to_bits(sizeof(xlen), min(signed(rs2_val), signed(loaded))), + AMOMAX => to_bits(sizeof(xlen), max(signed(rs2_val), signed(loaded))), + AMOMINU => to_bits(sizeof(xlen), min(unsigned(rs2_val), unsigned(loaded))), + AMOMAXU => to_bits(sizeof(xlen), max(unsigned(rs2_val), unsigned(loaded))) + }; + let rval : xlenbits = match width { + BYTE => sign_extend(loaded[7..0]), + HALF => sign_extend(loaded[15..0]), + WORD => sign_extend(loaded[31..0]), + DOUBLE => loaded + }; + let wval : MemoryOpResult(bool) = match (width, sizeof(xlen)) { + (BYTE, _) => mem_write_value(addr, 1, result[7..0], aq & rl, rl, true), + (HALF, _) => mem_write_value(addr, 2, result[15..0], aq & rl, rl, true), + (WORD, _) => mem_write_value(addr, 4, result[31..0], aq & rl, rl, true), + (DOUBLE, 64) => mem_write_value(addr, 8, result, aq & rl, rl, true), + _ => internal_error(__FILE__, __LINE__, "Unexpected AMO width") + }; + match (wval) { + MemValue(true) => { X(rd) = rval; RETIRE_SUCCESS }, + MemValue(false) => { internal_error(__FILE__, __LINE__, "AMO got false from mem_write_value") }, + MemException(e) => { handle_mem_exception(vaddr, e); RETIRE_FAIL } + } + } + } + } + } + } + } + } + } + } else { + handle_illegal(); + RETIRE_FAIL + } + } + +# SPDX-SnippetEnd diff --git a/spec/std/isa/inst/Zaamo/amoadd.w.aqrl.yaml b/spec/std/isa/inst/Zaamo/amoadd.w.aqrl.yaml new file mode 100644 index 0000000000..7e79447005 --- /dev/null +++ b/spec/std/isa/inst/Zaamo/amoadd.w.aqrl.yaml @@ -0,0 +1,141 @@ +# Copyright (c) Qualcomm Technologies, Inc. and/or its subsidiaries. + +# WARNING: This file is auto-generated from spec/std/isa/inst/Zaamo/amoadd.SIZE.AQRL.layout# Copyright (c) Abhijit Das(Sukuna0007Abhi) +# SPDX-License-Identifier: BSD-3-Clause-Clear + +# yaml-language-server: $schema=../../../../schemas/inst_schema.json + +$schema: "inst_schema.json#" +kind: instruction +name: amoadd.w.aqrl +long_name: Atomic fetch-and-add word (acquire-release) +description: | + Atomically with acquire and release ordering: + + * Load the word at address _xs1_ + * Write the sign-extended value into _xd_ + * Add the least-significant word of register _xs2_ to the loaded value + * Write the result to the address in _xs1_ +definedBy: Zaamo +assembly: xd, xs2, (xs1) +encoding: + match: 0000011----------010-----0101111 + variables: + - name: xs2 + location: 24-20 + - name: xs1 + location: 19-15 + - name: xd + location: 11-7 +access: + s: always + u: always + vs: always + vu: always +operation(): | + if (!implemented?(ExtensionName::A) || (MISA_CSR_IMPLEMENTED && (CSR[misa].A == 1'b0))) { + raise (ExceptionCode::IllegalInstruction, mode(), $encoding); + } + + memory_model_acquire(); + + XReg virtual_address = X[xs1]; + X[xd] = amo<32>(virtual_address, X[xs2][31:0], AmoOperation::Add, 1'b1, 1'b1, $encoding); + + memory_model_release(); + +# SPDX-SnippetBegin +# SPDX-FileCopyrightText: 2017-2025 Contributors to the RISCV Sail Model +# SPDX-License-Identifier: BSD-2-Clause +sail(): | + { + if extension("A") then { + /* Get the address, X(rs1) (no offset). + * Some extensions perform additional checks on address validity. + */ + match ext_data_get_addr(rs1, zeros(), ReadWrite(Data, Data), width) { + Ext_DataAddr_Error(e) => { ext_handle_data_check_error(e); RETIRE_FAIL }, + Ext_DataAddr_OK(vaddr) => { + match translateAddr(vaddr, ReadWrite(Data, Data)) { + TR_Failure(e, _) => { handle_mem_exception(vaddr, e); RETIRE_FAIL }, + TR_Address(addr, _) => { + let eares : MemoryOpResult(unit) = match (width, sizeof(xlen)) { + (BYTE, _) => mem_write_ea(addr, 1, aq & rl, rl, true), + (HALF, _) => mem_write_ea(addr, 2, aq & rl, rl, true), + (WORD, _) => mem_write_ea(addr, 4, aq & rl, rl, true), + (DOUBLE, 64) => mem_write_ea(addr, 8, aq & rl, rl, true), + _ => internal_error(__FILE__, __LINE__, "Unexpected AMO width") + }; + let is_unsigned : bool = match op { + AMOMINU => true, + AMOMAXU => true, + _ => false + }; + let rs2_val : xlenbits = match width { + BYTE => if is_unsigned then zero_extend(X(rs2)[7..0]) else sign_extend(X(rs2)[7..0]), + HALF => if is_unsigned then zero_extend(X(rs2)[15..0]) else sign_extend(X(rs2)[15..0]), + WORD => if is_unsigned then zero_extend(X(rs2)[31..0]) else sign_extend(X(rs2)[31..0]), + DOUBLE => X(rs2) + }; + match (eares) { + MemException(e) => { handle_mem_exception(vaddr, e); RETIRE_FAIL }, + MemValue(_) => { + let mval : MemoryOpResult(xlenbits) = match (width, sizeof(xlen)) { + (BYTE, _) => extend_value(is_unsigned, mem_read(ReadWrite(Data, Data), addr, 1, aq, aq & rl, true)), + (HALF, _) => extend_value(is_unsigned, mem_read(ReadWrite(Data, Data), addr, 2, aq, aq & rl, true)), + (WORD, _) => extend_value(is_unsigned, mem_read(ReadWrite(Data, Data), addr, 4, aq, aq & rl, true)), + (DOUBLE, 64) => extend_value(is_unsigned, mem_read(ReadWrite(Data, Data), addr, 8, aq, aq & rl, true)), + _ => internal_error(__FILE__, __LINE__, "Unexpected AMO width") + }; + match (mval) { + MemException(e) => { handle_mem_exception(vaddr, e); RETIRE_FAIL }, + MemValue(loaded) => { + let result : xlenbits = + match op { + AMOSWAP => rs2_val, + AMOADD => rs2_val + loaded, + AMOXOR => rs2_val ^ loaded, + AMOAND => rs2_val & loaded, + AMOOR => rs2_val | loaded, + + /* These operations convert bitvectors to integer values using [un]signed, + * and back using to_bits(). + */ + AMOMIN => to_bits(sizeof(xlen), min(signed(rs2_val), signed(loaded))), + AMOMAX => to_bits(sizeof(xlen), max(signed(rs2_val), signed(loaded))), + AMOMINU => to_bits(sizeof(xlen), min(unsigned(rs2_val), unsigned(loaded))), + AMOMAXU => to_bits(sizeof(xlen), max(unsigned(rs2_val), unsigned(loaded))) + }; + let rval : xlenbits = match width { + BYTE => sign_extend(loaded[7..0]), + HALF => sign_extend(loaded[15..0]), + WORD => sign_extend(loaded[31..0]), + DOUBLE => loaded + }; + let wval : MemoryOpResult(bool) = match (width, sizeof(xlen)) { + (BYTE, _) => mem_write_value(addr, 1, result[7..0], aq & rl, rl, true), + (HALF, _) => mem_write_value(addr, 2, result[15..0], aq & rl, rl, true), + (WORD, _) => mem_write_value(addr, 4, result[31..0], aq & rl, rl, true), + (DOUBLE, 64) => mem_write_value(addr, 8, result, aq & rl, rl, true), + _ => internal_error(__FILE__, __LINE__, "Unexpected AMO width") + }; + match (wval) { + MemValue(true) => { X(rd) = rval; RETIRE_SUCCESS }, + MemValue(false) => { internal_error(__FILE__, __LINE__, "AMO got false from mem_write_value") }, + MemException(e) => { handle_mem_exception(vaddr, e); RETIRE_FAIL } + } + } + } + } + } + } + } + } + } + } else { + handle_illegal(); + RETIRE_FAIL + } + } + +# SPDX-SnippetEnd diff --git a/spec/std/isa/inst/Zaamo/amoadd.w.rl.yaml b/spec/std/isa/inst/Zaamo/amoadd.w.rl.yaml new file mode 100644 index 0000000000..37fada8808 --- /dev/null +++ b/spec/std/isa/inst/Zaamo/amoadd.w.rl.yaml @@ -0,0 +1,139 @@ +# Copyright (c) Qualcomm Technologies, Inc. and/or its subsidiaries. + +# WARNING: This file is auto-generated from spec/std/isa/inst/Zaamo/amoadd.SIZE.AQRL.layout# Copyright (c) Abhijit Das(Sukuna0007Abhi) +# SPDX-License-Identifier: BSD-3-Clause-Clear + +# yaml-language-server: $schema=../../../../schemas/inst_schema.json + +$schema: "inst_schema.json#" +kind: instruction +name: amoadd.w.rl +long_name: Atomic fetch-and-add word (release) +description: | + Atomically with release ordering: + + * Load the word at address _xs1_ + * Write the sign-extended value into _xd_ + * Add the least-significant word of register _xs2_ to the loaded value + * Write the result to the address in _xs1_ +definedBy: Zaamo +assembly: xd, xs2, (xs1) +encoding: + match: 0000001----------010-----0101111 + variables: + - name: xs2 + location: 24-20 + - name: xs1 + location: 19-15 + - name: xd + location: 11-7 +access: + s: always + u: always + vs: always + vu: always +operation(): | + if (!implemented?(ExtensionName::A) || (MISA_CSR_IMPLEMENTED && (CSR[misa].A == 1'b0))) { + raise (ExceptionCode::IllegalInstruction, mode(), $encoding); + } + + XReg virtual_address = X[xs1]; + X[xd] = amo<32>(virtual_address, X[xs2][31:0], AmoOperation::Add, 1'b0, 1'b1, $encoding); + + memory_model_release(); + +# SPDX-SnippetBegin +# SPDX-FileCopyrightText: 2017-2025 Contributors to the RISCV Sail Model +# SPDX-License-Identifier: BSD-2-Clause +sail(): | + { + if extension("A") then { + /* Get the address, X(rs1) (no offset). + * Some extensions perform additional checks on address validity. + */ + match ext_data_get_addr(rs1, zeros(), ReadWrite(Data, Data), width) { + Ext_DataAddr_Error(e) => { ext_handle_data_check_error(e); RETIRE_FAIL }, + Ext_DataAddr_OK(vaddr) => { + match translateAddr(vaddr, ReadWrite(Data, Data)) { + TR_Failure(e, _) => { handle_mem_exception(vaddr, e); RETIRE_FAIL }, + TR_Address(addr, _) => { + let eares : MemoryOpResult(unit) = match (width, sizeof(xlen)) { + (BYTE, _) => mem_write_ea(addr, 1, aq & rl, rl, true), + (HALF, _) => mem_write_ea(addr, 2, aq & rl, rl, true), + (WORD, _) => mem_write_ea(addr, 4, aq & rl, rl, true), + (DOUBLE, 64) => mem_write_ea(addr, 8, aq & rl, rl, true), + _ => internal_error(__FILE__, __LINE__, "Unexpected AMO width") + }; + let is_unsigned : bool = match op { + AMOMINU => true, + AMOMAXU => true, + _ => false + }; + let rs2_val : xlenbits = match width { + BYTE => if is_unsigned then zero_extend(X(rs2)[7..0]) else sign_extend(X(rs2)[7..0]), + HALF => if is_unsigned then zero_extend(X(rs2)[15..0]) else sign_extend(X(rs2)[15..0]), + WORD => if is_unsigned then zero_extend(X(rs2)[31..0]) else sign_extend(X(rs2)[31..0]), + DOUBLE => X(rs2) + }; + match (eares) { + MemException(e) => { handle_mem_exception(vaddr, e); RETIRE_FAIL }, + MemValue(_) => { + let mval : MemoryOpResult(xlenbits) = match (width, sizeof(xlen)) { + (BYTE, _) => extend_value(is_unsigned, mem_read(ReadWrite(Data, Data), addr, 1, aq, aq & rl, true)), + (HALF, _) => extend_value(is_unsigned, mem_read(ReadWrite(Data, Data), addr, 2, aq, aq & rl, true)), + (WORD, _) => extend_value(is_unsigned, mem_read(ReadWrite(Data, Data), addr, 4, aq, aq & rl, true)), + (DOUBLE, 64) => extend_value(is_unsigned, mem_read(ReadWrite(Data, Data), addr, 8, aq, aq & rl, true)), + _ => internal_error(__FILE__, __LINE__, "Unexpected AMO width") + }; + match (mval) { + MemException(e) => { handle_mem_exception(vaddr, e); RETIRE_FAIL }, + MemValue(loaded) => { + let result : xlenbits = + match op { + AMOSWAP => rs2_val, + AMOADD => rs2_val + loaded, + AMOXOR => rs2_val ^ loaded, + AMOAND => rs2_val & loaded, + AMOOR => rs2_val | loaded, + + /* These operations convert bitvectors to integer values using [un]signed, + * and back using to_bits(). + */ + AMOMIN => to_bits(sizeof(xlen), min(signed(rs2_val), signed(loaded))), + AMOMAX => to_bits(sizeof(xlen), max(signed(rs2_val), signed(loaded))), + AMOMINU => to_bits(sizeof(xlen), min(unsigned(rs2_val), unsigned(loaded))), + AMOMAXU => to_bits(sizeof(xlen), max(unsigned(rs2_val), unsigned(loaded))) + }; + let rval : xlenbits = match width { + BYTE => sign_extend(loaded[7..0]), + HALF => sign_extend(loaded[15..0]), + WORD => sign_extend(loaded[31..0]), + DOUBLE => loaded + }; + let wval : MemoryOpResult(bool) = match (width, sizeof(xlen)) { + (BYTE, _) => mem_write_value(addr, 1, result[7..0], aq & rl, rl, true), + (HALF, _) => mem_write_value(addr, 2, result[15..0], aq & rl, rl, true), + (WORD, _) => mem_write_value(addr, 4, result[31..0], aq & rl, rl, true), + (DOUBLE, 64) => mem_write_value(addr, 8, result, aq & rl, rl, true), + _ => internal_error(__FILE__, __LINE__, "Unexpected AMO width") + }; + match (wval) { + MemValue(true) => { X(rd) = rval; RETIRE_SUCCESS }, + MemValue(false) => { internal_error(__FILE__, __LINE__, "AMO got false from mem_write_value") }, + MemException(e) => { handle_mem_exception(vaddr, e); RETIRE_FAIL } + } + } + } + } + } + } + } + } + } + } else { + handle_illegal(); + RETIRE_FAIL + } + } + +# SPDX-SnippetEnd diff --git a/spec/std/isa/inst/Zaamo/amoadd.w.yaml b/spec/std/isa/inst/Zaamo/amoadd.w.yaml index d5fa70c1d4..bf1907bb3f 100644 --- a/spec/std/isa/inst/Zaamo/amoadd.w.yaml +++ b/spec/std/isa/inst/Zaamo/amoadd.w.yaml @@ -1,4 +1,6 @@ # Copyright (c) Qualcomm Technologies, Inc. and/or its subsidiaries. + +# WARNING: This file is auto-generated from spec/std/isa/inst/Zaamo/amoadd.SIZE.AQRL.layout# Copyright (c) Abhijit Das(Sukuna0007Abhi) # SPDX-License-Identifier: BSD-3-Clause-Clear # yaml-language-server: $schema=../../../../schemas/inst_schema.json @@ -13,16 +15,12 @@ description: | * Load the word at address _xs1_ * Write the sign-extended value into _xd_ * Add the least-significant word of register _xs2_ to the loaded value - * Write the sum to the address in _xs1_ + * Write the result to the address in _xs1_ definedBy: Zaamo assembly: xd, xs2, (xs1) encoding: - match: 00000------------010-----0101111 + match: 0000000----------010-----0101111 variables: - - name: aq - location: 26 - - name: rl - location: 25 - name: xs2 location: 24-20 - name: xs1 @@ -35,15 +33,12 @@ access: vs: always vu: always operation(): | - if (implemented?(ExtensionName::A) && (CSR[misa].A == 1'b0)) { - # even though this is a memory operation, the exception occurs before that would be known, - # so mode() is the correct reporting mode rathat than effective_ldst_mode() + if (!implemented?(ExtensionName::A) || (MISA_CSR_IMPLEMENTED && (CSR[misa].A == 1'b0))) { raise (ExceptionCode::IllegalInstruction, mode(), $encoding); } XReg virtual_address = X[xs1]; - - X[xd] = amo<32>(virtual_address, X[xs2][31:0], AmoOperation::Add, aq, rl, $encoding); + X[xd] = amo<32>(virtual_address, X[xs2][31:0], AmoOperation::Add, 1'b0, 1'b0, $encoding); # SPDX-SnippetBegin # SPDX-FileCopyrightText: 2017-2025 Contributors to the RISCV Sail Model diff --git a/spec/std/isa/inst/Zaamo/amoand.SIZE.AQRL.layout b/spec/std/isa/inst/Zaamo/amoand.SIZE.AQRL.layout new file mode 100644 index 0000000000..5b36bb2e24 --- /dev/null +++ b/spec/std/isa/inst/Zaamo/amoand.SIZE.AQRL.layout @@ -0,0 +1,175 @@ +# Copyright (c) Qualcomm Technologies, Inc. and/or its subsidiaries. +# Copyright (c) Abhijit Das(Sukuna0007Abhi) +# SPDX-License-Identifier: BSD-3-Clause-Clear + +# yaml-language-server: $schema=../../../../schemas/inst_schema.json +<%- + raise "'size' must be defined as 'b', 'h', 'w', or 'd'" unless %w[b h w d].include?(size) + raise "'aq' must be defined as true or false" unless [true, false].include?(aq) + raise "'rl' must be defined as true or false" unless [true, false].include?(rl) + + size_info = { + "b" => { name: "byte", bits: 8, funct3: "000", operation_bits: "8" }, + "h" => { name: "halfword", bits: 16, funct3: "001", operation_bits: "16" }, + "w" => { name: "word", bits: 32, funct3: "010", operation_bits: "32" }, + "d" => { name: "doubleword", bits: 64, funct3: "011", operation_bits: "64" } + } + + current_size = size_info[size] + + # Generate instruction name suffix based on aq/rl + aq_rl_suffix = "" + if aq && rl + aq_rl_suffix = ".aqrl" + elsif aq + aq_rl_suffix = ".aq" + elsif rl + aq_rl_suffix = ".rl" + end + + # Generate match string with fixed aq/rl bits + aq_bit = aq ? "1" : "0" + rl_bit = rl ? "1" : "0" +-%> + +$schema: "inst_schema.json#" +kind: instruction +name: amoand.<%= size %><%= aq_rl_suffix %> +long_name: Atomic fetch-and-and <%= current_size[:name] %><%= aq && rl ? " (acquire-release)" : (aq ? " (acquire)" : (rl ? " (release)" : "")) %> +description: | + Atomically<%= aq && rl ? " with acquire and release ordering" : (aq ? " with acquire ordering" : (rl ? " with release ordering" : "")) %>: + + * Load the <%= current_size[:name] %> at address _xs1_ + * Write the <%= %w[b h w].include?(size) ? "sign-extended value" : "loaded value" %> into _xd_ + * AND the <%= %w[b h w].include?(size) ? "least-significant #{current_size[:name]} of register" : "value of register" %> _xs2_ to the loaded value + * Write the result to the address in _xs1_ +definedBy: <%= %w[b h].include?(size) ? "Zabha" : "Zaamo" %> +<%- if size == "d" -%> +base: 64 +<%- end -%> +assembly: xd, xs2, (xs1) +encoding: + match: 01100<%= aq_bit %><%= rl_bit %>----------<%= current_size[:funct3] %>-----0101111 + variables: + - name: xs2 + location: 24-20 + - name: xs1 + location: 19-15 + - name: xd + location: 11-7 +access: + s: always + u: always + vs: always + vu: always +operation(): | + if (!implemented?(ExtensionName::A) || (MISA_CSR_IMPLEMENTED && (CSR[misa].A == 1'b0))) { + raise (ExceptionCode::IllegalInstruction, mode(), $encoding); + } + +<% if aq -%> + memory_model_acquire(); + +<% end -%> + XReg virtual_address = X[xs1]; + X[xd] = amo<<%= current_size[:operation_bits] %>>(virtual_address, X[xs2]<%= %w[b h w].include?(size) ? "[#{current_size[:bits]-1}:0]" : "" %>, AmoOperation::And, <%= aq ? "1'b1" : "1'b0" %>, <%= rl ? "1'b1" : "1'b0" %>, $encoding); +<% if rl -%> + + memory_model_release(); +<% end -%> + +# SPDX-SnippetBegin +# SPDX-FileCopyrightText: 2017-2025 Contributors to the RISCV Sail Model +# SPDX-License-Identifier: BSD-2-Clause +sail(): | + { + if extension("A") then { + /* Get the address, X(rs1) (no offset). + * Some extensions perform additional checks on address validity. + */ + match ext_data_get_addr(rs1, zeros(), ReadWrite(Data, Data), width) { + Ext_DataAddr_Error(e) => { ext_handle_data_check_error(e); RETIRE_FAIL }, + Ext_DataAddr_OK(vaddr) => { + match translateAddr(vaddr, ReadWrite(Data, Data)) { + TR_Failure(e, _) => { handle_mem_exception(vaddr, e); RETIRE_FAIL }, + TR_Address(addr, _) => { + let eares : MemoryOpResult(unit) = match (width, sizeof(xlen)) { + (BYTE, _) => mem_write_ea(addr, 1, aq & rl, rl, true), + (HALF, _) => mem_write_ea(addr, 2, aq & rl, rl, true), + (WORD, _) => mem_write_ea(addr, 4, aq & rl, rl, true), + (DOUBLE, 64) => mem_write_ea(addr, 8, aq & rl, rl, true), + _ => internal_error(__FILE__, __LINE__, "Unexpected AMO width") + }; + let is_unsigned : bool = match op { + AMOMINU => true, + AMOMAXU => true, + _ => false + }; + let rs2_val : xlenbits = match width { + BYTE => if is_unsigned then zero_extend(X(rs2)[7..0]) else sign_extend(X(rs2)[7..0]), + HALF => if is_unsigned then zero_extend(X(rs2)[15..0]) else sign_extend(X(rs2)[15..0]), + WORD => if is_unsigned then zero_extend(X(rs2)[31..0]) else sign_extend(X(rs2)[31..0]), + DOUBLE => X(rs2) + }; + match (eares) { + MemException(e) => { handle_mem_exception(vaddr, e); RETIRE_FAIL }, + MemValue(_) => { + let mval : MemoryOpResult(xlenbits) = match (width, sizeof(xlen)) { + (BYTE, _) => extend_value(is_unsigned, mem_read(ReadWrite(Data, Data), addr, 1, aq, aq & rl, true)), + (HALF, _) => extend_value(is_unsigned, mem_read(ReadWrite(Data, Data), addr, 2, aq, aq & rl, true)), + (WORD, _) => extend_value(is_unsigned, mem_read(ReadWrite(Data, Data), addr, 4, aq, aq & rl, true)), + (DOUBLE, 64) => extend_value(is_unsigned, mem_read(ReadWrite(Data, Data), addr, 8, aq, aq & rl, true)), + _ => internal_error(__FILE__, __LINE__, "Unexpected AMO width") + }; + match (mval) { + MemException(e) => { handle_mem_exception(vaddr, e); RETIRE_FAIL }, + MemValue(loaded) => { + let result : xlenbits = + match op { + AMOSWAP => rs2_val, + AMOADD => rs2_val + loaded, + AMOXOR => rs2_val ^ loaded, + AMOAND => rs2_val & loaded, + AMOOR => rs2_val | loaded, + + /* These operations convert bitvectors to integer values using [un]signed, + * and back using to_bits(). + */ + AMOMIN => to_bits(sizeof(xlen), min(signed(rs2_val), signed(loaded))), + AMOMAX => to_bits(sizeof(xlen), max(signed(rs2_val), signed(loaded))), + AMOMINU => to_bits(sizeof(xlen), min(unsigned(rs2_val), unsigned(loaded))), + AMOMAXU => to_bits(sizeof(xlen), max(unsigned(rs2_val), unsigned(loaded))) + }; + let rval : xlenbits = match width { + BYTE => sign_extend(loaded[7..0]), + HALF => sign_extend(loaded[15..0]), + WORD => sign_extend(loaded[31..0]), + DOUBLE => loaded + }; + let wval : MemoryOpResult(bool) = match (width, sizeof(xlen)) { + (BYTE, _) => mem_write_value(addr, 1, result[7..0], aq & rl, rl, true), + (HALF, _) => mem_write_value(addr, 2, result[15..0], aq & rl, rl, true), + (WORD, _) => mem_write_value(addr, 4, result[31..0], aq & rl, rl, true), + (DOUBLE, 64) => mem_write_value(addr, 8, result, aq & rl, rl, true), + _ => internal_error(__FILE__, __LINE__, "Unexpected AMO width") + }; + match (wval) { + MemValue(true) => { X(rd) = rval; RETIRE_SUCCESS }, + MemValue(false) => { internal_error(__FILE__, __LINE__, "AMO got false from mem_write_value") }, + MemException(e) => { handle_mem_exception(vaddr, e); RETIRE_FAIL } + } + } + } + } + } + } + } + } + } + } else { + handle_illegal(); + RETIRE_FAIL + } + } + +# SPDX-SnippetEnd diff --git a/spec/std/isa/inst/Zaamo/amoand.d.aq.yaml b/spec/std/isa/inst/Zaamo/amoand.d.aq.yaml new file mode 100644 index 0000000000..e7e5e7265a --- /dev/null +++ b/spec/std/isa/inst/Zaamo/amoand.d.aq.yaml @@ -0,0 +1,140 @@ +# Copyright (c) Qualcomm Technologies, Inc. and/or its subsidiaries. + +# WARNING: This file is auto-generated from spec/std/isa/inst/Zaamo/amoand.SIZE.AQRL.layout# Copyright (c) Abhijit Das(Sukuna0007Abhi) +# SPDX-License-Identifier: BSD-3-Clause-Clear + +# yaml-language-server: $schema=../../../../schemas/inst_schema.json + +$schema: "inst_schema.json#" +kind: instruction +name: amoand.d.aq +long_name: Atomic fetch-and-and doubleword (acquire) +description: | + Atomically with acquire ordering: + + * Load the doubleword at address _xs1_ + * Write the loaded value into _xd_ + * AND the value of register _xs2_ to the loaded value + * Write the result to the address in _xs1_ +definedBy: Zaamo +base: 64 +assembly: xd, xs2, (xs1) +encoding: + match: 0110010----------011-----0101111 + variables: + - name: xs2 + location: 24-20 + - name: xs1 + location: 19-15 + - name: xd + location: 11-7 +access: + s: always + u: always + vs: always + vu: always +operation(): | + if (!implemented?(ExtensionName::A) || (MISA_CSR_IMPLEMENTED && (CSR[misa].A == 1'b0))) { + raise (ExceptionCode::IllegalInstruction, mode(), $encoding); + } + + memory_model_acquire(); + + XReg virtual_address = X[xs1]; + X[xd] = amo<64>(virtual_address, X[xs2], AmoOperation::And, 1'b1, 1'b0, $encoding); + +# SPDX-SnippetBegin +# SPDX-FileCopyrightText: 2017-2025 Contributors to the RISCV Sail Model +# SPDX-License-Identifier: BSD-2-Clause +sail(): | + { + if extension("A") then { + /* Get the address, X(rs1) (no offset). + * Some extensions perform additional checks on address validity. + */ + match ext_data_get_addr(rs1, zeros(), ReadWrite(Data, Data), width) { + Ext_DataAddr_Error(e) => { ext_handle_data_check_error(e); RETIRE_FAIL }, + Ext_DataAddr_OK(vaddr) => { + match translateAddr(vaddr, ReadWrite(Data, Data)) { + TR_Failure(e, _) => { handle_mem_exception(vaddr, e); RETIRE_FAIL }, + TR_Address(addr, _) => { + let eares : MemoryOpResult(unit) = match (width, sizeof(xlen)) { + (BYTE, _) => mem_write_ea(addr, 1, aq & rl, rl, true), + (HALF, _) => mem_write_ea(addr, 2, aq & rl, rl, true), + (WORD, _) => mem_write_ea(addr, 4, aq & rl, rl, true), + (DOUBLE, 64) => mem_write_ea(addr, 8, aq & rl, rl, true), + _ => internal_error(__FILE__, __LINE__, "Unexpected AMO width") + }; + let is_unsigned : bool = match op { + AMOMINU => true, + AMOMAXU => true, + _ => false + }; + let rs2_val : xlenbits = match width { + BYTE => if is_unsigned then zero_extend(X(rs2)[7..0]) else sign_extend(X(rs2)[7..0]), + HALF => if is_unsigned then zero_extend(X(rs2)[15..0]) else sign_extend(X(rs2)[15..0]), + WORD => if is_unsigned then zero_extend(X(rs2)[31..0]) else sign_extend(X(rs2)[31..0]), + DOUBLE => X(rs2) + }; + match (eares) { + MemException(e) => { handle_mem_exception(vaddr, e); RETIRE_FAIL }, + MemValue(_) => { + let mval : MemoryOpResult(xlenbits) = match (width, sizeof(xlen)) { + (BYTE, _) => extend_value(is_unsigned, mem_read(ReadWrite(Data, Data), addr, 1, aq, aq & rl, true)), + (HALF, _) => extend_value(is_unsigned, mem_read(ReadWrite(Data, Data), addr, 2, aq, aq & rl, true)), + (WORD, _) => extend_value(is_unsigned, mem_read(ReadWrite(Data, Data), addr, 4, aq, aq & rl, true)), + (DOUBLE, 64) => extend_value(is_unsigned, mem_read(ReadWrite(Data, Data), addr, 8, aq, aq & rl, true)), + _ => internal_error(__FILE__, __LINE__, "Unexpected AMO width") + }; + match (mval) { + MemException(e) => { handle_mem_exception(vaddr, e); RETIRE_FAIL }, + MemValue(loaded) => { + let result : xlenbits = + match op { + AMOSWAP => rs2_val, + AMOADD => rs2_val + loaded, + AMOXOR => rs2_val ^ loaded, + AMOAND => rs2_val & loaded, + AMOOR => rs2_val | loaded, + + /* These operations convert bitvectors to integer values using [un]signed, + * and back using to_bits(). + */ + AMOMIN => to_bits(sizeof(xlen), min(signed(rs2_val), signed(loaded))), + AMOMAX => to_bits(sizeof(xlen), max(signed(rs2_val), signed(loaded))), + AMOMINU => to_bits(sizeof(xlen), min(unsigned(rs2_val), unsigned(loaded))), + AMOMAXU => to_bits(sizeof(xlen), max(unsigned(rs2_val), unsigned(loaded))) + }; + let rval : xlenbits = match width { + BYTE => sign_extend(loaded[7..0]), + HALF => sign_extend(loaded[15..0]), + WORD => sign_extend(loaded[31..0]), + DOUBLE => loaded + }; + let wval : MemoryOpResult(bool) = match (width, sizeof(xlen)) { + (BYTE, _) => mem_write_value(addr, 1, result[7..0], aq & rl, rl, true), + (HALF, _) => mem_write_value(addr, 2, result[15..0], aq & rl, rl, true), + (WORD, _) => mem_write_value(addr, 4, result[31..0], aq & rl, rl, true), + (DOUBLE, 64) => mem_write_value(addr, 8, result, aq & rl, rl, true), + _ => internal_error(__FILE__, __LINE__, "Unexpected AMO width") + }; + match (wval) { + MemValue(true) => { X(rd) = rval; RETIRE_SUCCESS }, + MemValue(false) => { internal_error(__FILE__, __LINE__, "AMO got false from mem_write_value") }, + MemException(e) => { handle_mem_exception(vaddr, e); RETIRE_FAIL } + } + } + } + } + } + } + } + } + } + } else { + handle_illegal(); + RETIRE_FAIL + } + } + +# SPDX-SnippetEnd diff --git a/spec/std/isa/inst/Zaamo/amoand.d.aqrl.yaml b/spec/std/isa/inst/Zaamo/amoand.d.aqrl.yaml new file mode 100644 index 0000000000..b7aee870bd --- /dev/null +++ b/spec/std/isa/inst/Zaamo/amoand.d.aqrl.yaml @@ -0,0 +1,142 @@ +# Copyright (c) Qualcomm Technologies, Inc. and/or its subsidiaries. + +# WARNING: This file is auto-generated from spec/std/isa/inst/Zaamo/amoand.SIZE.AQRL.layout# Copyright (c) Abhijit Das(Sukuna0007Abhi) +# SPDX-License-Identifier: BSD-3-Clause-Clear + +# yaml-language-server: $schema=../../../../schemas/inst_schema.json + +$schema: "inst_schema.json#" +kind: instruction +name: amoand.d.aqrl +long_name: Atomic fetch-and-and doubleword (acquire-release) +description: | + Atomically with acquire and release ordering: + + * Load the doubleword at address _xs1_ + * Write the loaded value into _xd_ + * AND the value of register _xs2_ to the loaded value + * Write the result to the address in _xs1_ +definedBy: Zaamo +base: 64 +assembly: xd, xs2, (xs1) +encoding: + match: 0110011----------011-----0101111 + variables: + - name: xs2 + location: 24-20 + - name: xs1 + location: 19-15 + - name: xd + location: 11-7 +access: + s: always + u: always + vs: always + vu: always +operation(): | + if (!implemented?(ExtensionName::A) || (MISA_CSR_IMPLEMENTED && (CSR[misa].A == 1'b0))) { + raise (ExceptionCode::IllegalInstruction, mode(), $encoding); + } + + memory_model_acquire(); + + XReg virtual_address = X[xs1]; + X[xd] = amo<64>(virtual_address, X[xs2], AmoOperation::And, 1'b1, 1'b1, $encoding); + + memory_model_release(); + +# SPDX-SnippetBegin +# SPDX-FileCopyrightText: 2017-2025 Contributors to the RISCV Sail Model +# SPDX-License-Identifier: BSD-2-Clause +sail(): | + { + if extension("A") then { + /* Get the address, X(rs1) (no offset). + * Some extensions perform additional checks on address validity. + */ + match ext_data_get_addr(rs1, zeros(), ReadWrite(Data, Data), width) { + Ext_DataAddr_Error(e) => { ext_handle_data_check_error(e); RETIRE_FAIL }, + Ext_DataAddr_OK(vaddr) => { + match translateAddr(vaddr, ReadWrite(Data, Data)) { + TR_Failure(e, _) => { handle_mem_exception(vaddr, e); RETIRE_FAIL }, + TR_Address(addr, _) => { + let eares : MemoryOpResult(unit) = match (width, sizeof(xlen)) { + (BYTE, _) => mem_write_ea(addr, 1, aq & rl, rl, true), + (HALF, _) => mem_write_ea(addr, 2, aq & rl, rl, true), + (WORD, _) => mem_write_ea(addr, 4, aq & rl, rl, true), + (DOUBLE, 64) => mem_write_ea(addr, 8, aq & rl, rl, true), + _ => internal_error(__FILE__, __LINE__, "Unexpected AMO width") + }; + let is_unsigned : bool = match op { + AMOMINU => true, + AMOMAXU => true, + _ => false + }; + let rs2_val : xlenbits = match width { + BYTE => if is_unsigned then zero_extend(X(rs2)[7..0]) else sign_extend(X(rs2)[7..0]), + HALF => if is_unsigned then zero_extend(X(rs2)[15..0]) else sign_extend(X(rs2)[15..0]), + WORD => if is_unsigned then zero_extend(X(rs2)[31..0]) else sign_extend(X(rs2)[31..0]), + DOUBLE => X(rs2) + }; + match (eares) { + MemException(e) => { handle_mem_exception(vaddr, e); RETIRE_FAIL }, + MemValue(_) => { + let mval : MemoryOpResult(xlenbits) = match (width, sizeof(xlen)) { + (BYTE, _) => extend_value(is_unsigned, mem_read(ReadWrite(Data, Data), addr, 1, aq, aq & rl, true)), + (HALF, _) => extend_value(is_unsigned, mem_read(ReadWrite(Data, Data), addr, 2, aq, aq & rl, true)), + (WORD, _) => extend_value(is_unsigned, mem_read(ReadWrite(Data, Data), addr, 4, aq, aq & rl, true)), + (DOUBLE, 64) => extend_value(is_unsigned, mem_read(ReadWrite(Data, Data), addr, 8, aq, aq & rl, true)), + _ => internal_error(__FILE__, __LINE__, "Unexpected AMO width") + }; + match (mval) { + MemException(e) => { handle_mem_exception(vaddr, e); RETIRE_FAIL }, + MemValue(loaded) => { + let result : xlenbits = + match op { + AMOSWAP => rs2_val, + AMOADD => rs2_val + loaded, + AMOXOR => rs2_val ^ loaded, + AMOAND => rs2_val & loaded, + AMOOR => rs2_val | loaded, + + /* These operations convert bitvectors to integer values using [un]signed, + * and back using to_bits(). + */ + AMOMIN => to_bits(sizeof(xlen), min(signed(rs2_val), signed(loaded))), + AMOMAX => to_bits(sizeof(xlen), max(signed(rs2_val), signed(loaded))), + AMOMINU => to_bits(sizeof(xlen), min(unsigned(rs2_val), unsigned(loaded))), + AMOMAXU => to_bits(sizeof(xlen), max(unsigned(rs2_val), unsigned(loaded))) + }; + let rval : xlenbits = match width { + BYTE => sign_extend(loaded[7..0]), + HALF => sign_extend(loaded[15..0]), + WORD => sign_extend(loaded[31..0]), + DOUBLE => loaded + }; + let wval : MemoryOpResult(bool) = match (width, sizeof(xlen)) { + (BYTE, _) => mem_write_value(addr, 1, result[7..0], aq & rl, rl, true), + (HALF, _) => mem_write_value(addr, 2, result[15..0], aq & rl, rl, true), + (WORD, _) => mem_write_value(addr, 4, result[31..0], aq & rl, rl, true), + (DOUBLE, 64) => mem_write_value(addr, 8, result, aq & rl, rl, true), + _ => internal_error(__FILE__, __LINE__, "Unexpected AMO width") + }; + match (wval) { + MemValue(true) => { X(rd) = rval; RETIRE_SUCCESS }, + MemValue(false) => { internal_error(__FILE__, __LINE__, "AMO got false from mem_write_value") }, + MemException(e) => { handle_mem_exception(vaddr, e); RETIRE_FAIL } + } + } + } + } + } + } + } + } + } + } else { + handle_illegal(); + RETIRE_FAIL + } + } + +# SPDX-SnippetEnd diff --git a/spec/std/isa/inst/Zaamo/amoand.d.rl.yaml b/spec/std/isa/inst/Zaamo/amoand.d.rl.yaml new file mode 100644 index 0000000000..4970382727 --- /dev/null +++ b/spec/std/isa/inst/Zaamo/amoand.d.rl.yaml @@ -0,0 +1,140 @@ +# Copyright (c) Qualcomm Technologies, Inc. and/or its subsidiaries. + +# WARNING: This file is auto-generated from spec/std/isa/inst/Zaamo/amoand.SIZE.AQRL.layout# Copyright (c) Abhijit Das(Sukuna0007Abhi) +# SPDX-License-Identifier: BSD-3-Clause-Clear + +# yaml-language-server: $schema=../../../../schemas/inst_schema.json + +$schema: "inst_schema.json#" +kind: instruction +name: amoand.d.rl +long_name: Atomic fetch-and-and doubleword (release) +description: | + Atomically with release ordering: + + * Load the doubleword at address _xs1_ + * Write the loaded value into _xd_ + * AND the value of register _xs2_ to the loaded value + * Write the result to the address in _xs1_ +definedBy: Zaamo +base: 64 +assembly: xd, xs2, (xs1) +encoding: + match: 0110001----------011-----0101111 + variables: + - name: xs2 + location: 24-20 + - name: xs1 + location: 19-15 + - name: xd + location: 11-7 +access: + s: always + u: always + vs: always + vu: always +operation(): | + if (!implemented?(ExtensionName::A) || (MISA_CSR_IMPLEMENTED && (CSR[misa].A == 1'b0))) { + raise (ExceptionCode::IllegalInstruction, mode(), $encoding); + } + + XReg virtual_address = X[xs1]; + X[xd] = amo<64>(virtual_address, X[xs2], AmoOperation::And, 1'b0, 1'b1, $encoding); + + memory_model_release(); + +# SPDX-SnippetBegin +# SPDX-FileCopyrightText: 2017-2025 Contributors to the RISCV Sail Model +# SPDX-License-Identifier: BSD-2-Clause +sail(): | + { + if extension("A") then { + /* Get the address, X(rs1) (no offset). + * Some extensions perform additional checks on address validity. + */ + match ext_data_get_addr(rs1, zeros(), ReadWrite(Data, Data), width) { + Ext_DataAddr_Error(e) => { ext_handle_data_check_error(e); RETIRE_FAIL }, + Ext_DataAddr_OK(vaddr) => { + match translateAddr(vaddr, ReadWrite(Data, Data)) { + TR_Failure(e, _) => { handle_mem_exception(vaddr, e); RETIRE_FAIL }, + TR_Address(addr, _) => { + let eares : MemoryOpResult(unit) = match (width, sizeof(xlen)) { + (BYTE, _) => mem_write_ea(addr, 1, aq & rl, rl, true), + (HALF, _) => mem_write_ea(addr, 2, aq & rl, rl, true), + (WORD, _) => mem_write_ea(addr, 4, aq & rl, rl, true), + (DOUBLE, 64) => mem_write_ea(addr, 8, aq & rl, rl, true), + _ => internal_error(__FILE__, __LINE__, "Unexpected AMO width") + }; + let is_unsigned : bool = match op { + AMOMINU => true, + AMOMAXU => true, + _ => false + }; + let rs2_val : xlenbits = match width { + BYTE => if is_unsigned then zero_extend(X(rs2)[7..0]) else sign_extend(X(rs2)[7..0]), + HALF => if is_unsigned then zero_extend(X(rs2)[15..0]) else sign_extend(X(rs2)[15..0]), + WORD => if is_unsigned then zero_extend(X(rs2)[31..0]) else sign_extend(X(rs2)[31..0]), + DOUBLE => X(rs2) + }; + match (eares) { + MemException(e) => { handle_mem_exception(vaddr, e); RETIRE_FAIL }, + MemValue(_) => { + let mval : MemoryOpResult(xlenbits) = match (width, sizeof(xlen)) { + (BYTE, _) => extend_value(is_unsigned, mem_read(ReadWrite(Data, Data), addr, 1, aq, aq & rl, true)), + (HALF, _) => extend_value(is_unsigned, mem_read(ReadWrite(Data, Data), addr, 2, aq, aq & rl, true)), + (WORD, _) => extend_value(is_unsigned, mem_read(ReadWrite(Data, Data), addr, 4, aq, aq & rl, true)), + (DOUBLE, 64) => extend_value(is_unsigned, mem_read(ReadWrite(Data, Data), addr, 8, aq, aq & rl, true)), + _ => internal_error(__FILE__, __LINE__, "Unexpected AMO width") + }; + match (mval) { + MemException(e) => { handle_mem_exception(vaddr, e); RETIRE_FAIL }, + MemValue(loaded) => { + let result : xlenbits = + match op { + AMOSWAP => rs2_val, + AMOADD => rs2_val + loaded, + AMOXOR => rs2_val ^ loaded, + AMOAND => rs2_val & loaded, + AMOOR => rs2_val | loaded, + + /* These operations convert bitvectors to integer values using [un]signed, + * and back using to_bits(). + */ + AMOMIN => to_bits(sizeof(xlen), min(signed(rs2_val), signed(loaded))), + AMOMAX => to_bits(sizeof(xlen), max(signed(rs2_val), signed(loaded))), + AMOMINU => to_bits(sizeof(xlen), min(unsigned(rs2_val), unsigned(loaded))), + AMOMAXU => to_bits(sizeof(xlen), max(unsigned(rs2_val), unsigned(loaded))) + }; + let rval : xlenbits = match width { + BYTE => sign_extend(loaded[7..0]), + HALF => sign_extend(loaded[15..0]), + WORD => sign_extend(loaded[31..0]), + DOUBLE => loaded + }; + let wval : MemoryOpResult(bool) = match (width, sizeof(xlen)) { + (BYTE, _) => mem_write_value(addr, 1, result[7..0], aq & rl, rl, true), + (HALF, _) => mem_write_value(addr, 2, result[15..0], aq & rl, rl, true), + (WORD, _) => mem_write_value(addr, 4, result[31..0], aq & rl, rl, true), + (DOUBLE, 64) => mem_write_value(addr, 8, result, aq & rl, rl, true), + _ => internal_error(__FILE__, __LINE__, "Unexpected AMO width") + }; + match (wval) { + MemValue(true) => { X(rd) = rval; RETIRE_SUCCESS }, + MemValue(false) => { internal_error(__FILE__, __LINE__, "AMO got false from mem_write_value") }, + MemException(e) => { handle_mem_exception(vaddr, e); RETIRE_FAIL } + } + } + } + } + } + } + } + } + } + } else { + handle_illegal(); + RETIRE_FAIL + } + } + +# SPDX-SnippetEnd diff --git a/spec/std/isa/inst/Zaamo/amoand.d.yaml b/spec/std/isa/inst/Zaamo/amoand.d.yaml index a1377ec753..11d74970a8 100644 --- a/spec/std/isa/inst/Zaamo/amoand.d.yaml +++ b/spec/std/isa/inst/Zaamo/amoand.d.yaml @@ -1,4 +1,6 @@ # Copyright (c) Qualcomm Technologies, Inc. and/or its subsidiaries. + +# WARNING: This file is auto-generated from spec/std/isa/inst/Zaamo/amoand.SIZE.AQRL.layout# Copyright (c) Abhijit Das(Sukuna0007Abhi) # SPDX-License-Identifier: BSD-3-Clause-Clear # yaml-language-server: $schema=../../../../schemas/inst_schema.json @@ -18,12 +20,8 @@ definedBy: Zaamo base: 64 assembly: xd, xs2, (xs1) encoding: - match: 01100------------011-----0101111 + match: 0110000----------011-----0101111 variables: - - name: aq - location: 26 - - name: rl - location: 25 - name: xs2 location: 24-20 - name: xs1 @@ -36,15 +34,12 @@ access: vs: always vu: always operation(): | - if (implemented?(ExtensionName::A) && (CSR[misa].A == 1'b0)) { - # even though this is a memory operation, the exception occurs before that would be known, - # so mode() is the correct reporting mode rathat than effective_ldst_mode() + if (!implemented?(ExtensionName::A) || (MISA_CSR_IMPLEMENTED && (CSR[misa].A == 1'b0))) { raise (ExceptionCode::IllegalInstruction, mode(), $encoding); } XReg virtual_address = X[xs1]; - - X[xd] = amo<64>(virtual_address, X[xs2], AmoOperation::And, aq, rl, $encoding); + X[xd] = amo<64>(virtual_address, X[xs2], AmoOperation::And, 1'b0, 1'b0, $encoding); # SPDX-SnippetBegin # SPDX-FileCopyrightText: 2017-2025 Contributors to the RISCV Sail Model diff --git a/spec/std/isa/inst/Zaamo/amoand.w.aq.yaml b/spec/std/isa/inst/Zaamo/amoand.w.aq.yaml new file mode 100644 index 0000000000..7a0b992078 --- /dev/null +++ b/spec/std/isa/inst/Zaamo/amoand.w.aq.yaml @@ -0,0 +1,139 @@ +# Copyright (c) Qualcomm Technologies, Inc. and/or its subsidiaries. + +# WARNING: This file is auto-generated from spec/std/isa/inst/Zaamo/amoand.SIZE.AQRL.layout# Copyright (c) Abhijit Das(Sukuna0007Abhi) +# SPDX-License-Identifier: BSD-3-Clause-Clear + +# yaml-language-server: $schema=../../../../schemas/inst_schema.json + +$schema: "inst_schema.json#" +kind: instruction +name: amoand.w.aq +long_name: Atomic fetch-and-and word (acquire) +description: | + Atomically with acquire ordering: + + * Load the word at address _xs1_ + * Write the sign-extended value into _xd_ + * AND the least-significant word of register _xs2_ to the loaded value + * Write the result to the address in _xs1_ +definedBy: Zaamo +assembly: xd, xs2, (xs1) +encoding: + match: 0110010----------010-----0101111 + variables: + - name: xs2 + location: 24-20 + - name: xs1 + location: 19-15 + - name: xd + location: 11-7 +access: + s: always + u: always + vs: always + vu: always +operation(): | + if (!implemented?(ExtensionName::A) || (MISA_CSR_IMPLEMENTED && (CSR[misa].A == 1'b0))) { + raise (ExceptionCode::IllegalInstruction, mode(), $encoding); + } + + memory_model_acquire(); + + XReg virtual_address = X[xs1]; + X[xd] = amo<32>(virtual_address, X[xs2][31:0], AmoOperation::And, 1'b1, 1'b0, $encoding); + +# SPDX-SnippetBegin +# SPDX-FileCopyrightText: 2017-2025 Contributors to the RISCV Sail Model +# SPDX-License-Identifier: BSD-2-Clause +sail(): | + { + if extension("A") then { + /* Get the address, X(rs1) (no offset). + * Some extensions perform additional checks on address validity. + */ + match ext_data_get_addr(rs1, zeros(), ReadWrite(Data, Data), width) { + Ext_DataAddr_Error(e) => { ext_handle_data_check_error(e); RETIRE_FAIL }, + Ext_DataAddr_OK(vaddr) => { + match translateAddr(vaddr, ReadWrite(Data, Data)) { + TR_Failure(e, _) => { handle_mem_exception(vaddr, e); RETIRE_FAIL }, + TR_Address(addr, _) => { + let eares : MemoryOpResult(unit) = match (width, sizeof(xlen)) { + (BYTE, _) => mem_write_ea(addr, 1, aq & rl, rl, true), + (HALF, _) => mem_write_ea(addr, 2, aq & rl, rl, true), + (WORD, _) => mem_write_ea(addr, 4, aq & rl, rl, true), + (DOUBLE, 64) => mem_write_ea(addr, 8, aq & rl, rl, true), + _ => internal_error(__FILE__, __LINE__, "Unexpected AMO width") + }; + let is_unsigned : bool = match op { + AMOMINU => true, + AMOMAXU => true, + _ => false + }; + let rs2_val : xlenbits = match width { + BYTE => if is_unsigned then zero_extend(X(rs2)[7..0]) else sign_extend(X(rs2)[7..0]), + HALF => if is_unsigned then zero_extend(X(rs2)[15..0]) else sign_extend(X(rs2)[15..0]), + WORD => if is_unsigned then zero_extend(X(rs2)[31..0]) else sign_extend(X(rs2)[31..0]), + DOUBLE => X(rs2) + }; + match (eares) { + MemException(e) => { handle_mem_exception(vaddr, e); RETIRE_FAIL }, + MemValue(_) => { + let mval : MemoryOpResult(xlenbits) = match (width, sizeof(xlen)) { + (BYTE, _) => extend_value(is_unsigned, mem_read(ReadWrite(Data, Data), addr, 1, aq, aq & rl, true)), + (HALF, _) => extend_value(is_unsigned, mem_read(ReadWrite(Data, Data), addr, 2, aq, aq & rl, true)), + (WORD, _) => extend_value(is_unsigned, mem_read(ReadWrite(Data, Data), addr, 4, aq, aq & rl, true)), + (DOUBLE, 64) => extend_value(is_unsigned, mem_read(ReadWrite(Data, Data), addr, 8, aq, aq & rl, true)), + _ => internal_error(__FILE__, __LINE__, "Unexpected AMO width") + }; + match (mval) { + MemException(e) => { handle_mem_exception(vaddr, e); RETIRE_FAIL }, + MemValue(loaded) => { + let result : xlenbits = + match op { + AMOSWAP => rs2_val, + AMOADD => rs2_val + loaded, + AMOXOR => rs2_val ^ loaded, + AMOAND => rs2_val & loaded, + AMOOR => rs2_val | loaded, + + /* These operations convert bitvectors to integer values using [un]signed, + * and back using to_bits(). + */ + AMOMIN => to_bits(sizeof(xlen), min(signed(rs2_val), signed(loaded))), + AMOMAX => to_bits(sizeof(xlen), max(signed(rs2_val), signed(loaded))), + AMOMINU => to_bits(sizeof(xlen), min(unsigned(rs2_val), unsigned(loaded))), + AMOMAXU => to_bits(sizeof(xlen), max(unsigned(rs2_val), unsigned(loaded))) + }; + let rval : xlenbits = match width { + BYTE => sign_extend(loaded[7..0]), + HALF => sign_extend(loaded[15..0]), + WORD => sign_extend(loaded[31..0]), + DOUBLE => loaded + }; + let wval : MemoryOpResult(bool) = match (width, sizeof(xlen)) { + (BYTE, _) => mem_write_value(addr, 1, result[7..0], aq & rl, rl, true), + (HALF, _) => mem_write_value(addr, 2, result[15..0], aq & rl, rl, true), + (WORD, _) => mem_write_value(addr, 4, result[31..0], aq & rl, rl, true), + (DOUBLE, 64) => mem_write_value(addr, 8, result, aq & rl, rl, true), + _ => internal_error(__FILE__, __LINE__, "Unexpected AMO width") + }; + match (wval) { + MemValue(true) => { X(rd) = rval; RETIRE_SUCCESS }, + MemValue(false) => { internal_error(__FILE__, __LINE__, "AMO got false from mem_write_value") }, + MemException(e) => { handle_mem_exception(vaddr, e); RETIRE_FAIL } + } + } + } + } + } + } + } + } + } + } else { + handle_illegal(); + RETIRE_FAIL + } + } + +# SPDX-SnippetEnd diff --git a/spec/std/isa/inst/Zaamo/amoand.w.aqrl.yaml b/spec/std/isa/inst/Zaamo/amoand.w.aqrl.yaml new file mode 100644 index 0000000000..9d9fc2fa62 --- /dev/null +++ b/spec/std/isa/inst/Zaamo/amoand.w.aqrl.yaml @@ -0,0 +1,141 @@ +# Copyright (c) Qualcomm Technologies, Inc. and/or its subsidiaries. + +# WARNING: This file is auto-generated from spec/std/isa/inst/Zaamo/amoand.SIZE.AQRL.layout# Copyright (c) Abhijit Das(Sukuna0007Abhi) +# SPDX-License-Identifier: BSD-3-Clause-Clear + +# yaml-language-server: $schema=../../../../schemas/inst_schema.json + +$schema: "inst_schema.json#" +kind: instruction +name: amoand.w.aqrl +long_name: Atomic fetch-and-and word (acquire-release) +description: | + Atomically with acquire and release ordering: + + * Load the word at address _xs1_ + * Write the sign-extended value into _xd_ + * AND the least-significant word of register _xs2_ to the loaded value + * Write the result to the address in _xs1_ +definedBy: Zaamo +assembly: xd, xs2, (xs1) +encoding: + match: 0110011----------010-----0101111 + variables: + - name: xs2 + location: 24-20 + - name: xs1 + location: 19-15 + - name: xd + location: 11-7 +access: + s: always + u: always + vs: always + vu: always +operation(): | + if (!implemented?(ExtensionName::A) || (MISA_CSR_IMPLEMENTED && (CSR[misa].A == 1'b0))) { + raise (ExceptionCode::IllegalInstruction, mode(), $encoding); + } + + memory_model_acquire(); + + XReg virtual_address = X[xs1]; + X[xd] = amo<32>(virtual_address, X[xs2][31:0], AmoOperation::And, 1'b1, 1'b1, $encoding); + + memory_model_release(); + +# SPDX-SnippetBegin +# SPDX-FileCopyrightText: 2017-2025 Contributors to the RISCV Sail Model +# SPDX-License-Identifier: BSD-2-Clause +sail(): | + { + if extension("A") then { + /* Get the address, X(rs1) (no offset). + * Some extensions perform additional checks on address validity. + */ + match ext_data_get_addr(rs1, zeros(), ReadWrite(Data, Data), width) { + Ext_DataAddr_Error(e) => { ext_handle_data_check_error(e); RETIRE_FAIL }, + Ext_DataAddr_OK(vaddr) => { + match translateAddr(vaddr, ReadWrite(Data, Data)) { + TR_Failure(e, _) => { handle_mem_exception(vaddr, e); RETIRE_FAIL }, + TR_Address(addr, _) => { + let eares : MemoryOpResult(unit) = match (width, sizeof(xlen)) { + (BYTE, _) => mem_write_ea(addr, 1, aq & rl, rl, true), + (HALF, _) => mem_write_ea(addr, 2, aq & rl, rl, true), + (WORD, _) => mem_write_ea(addr, 4, aq & rl, rl, true), + (DOUBLE, 64) => mem_write_ea(addr, 8, aq & rl, rl, true), + _ => internal_error(__FILE__, __LINE__, "Unexpected AMO width") + }; + let is_unsigned : bool = match op { + AMOMINU => true, + AMOMAXU => true, + _ => false + }; + let rs2_val : xlenbits = match width { + BYTE => if is_unsigned then zero_extend(X(rs2)[7..0]) else sign_extend(X(rs2)[7..0]), + HALF => if is_unsigned then zero_extend(X(rs2)[15..0]) else sign_extend(X(rs2)[15..0]), + WORD => if is_unsigned then zero_extend(X(rs2)[31..0]) else sign_extend(X(rs2)[31..0]), + DOUBLE => X(rs2) + }; + match (eares) { + MemException(e) => { handle_mem_exception(vaddr, e); RETIRE_FAIL }, + MemValue(_) => { + let mval : MemoryOpResult(xlenbits) = match (width, sizeof(xlen)) { + (BYTE, _) => extend_value(is_unsigned, mem_read(ReadWrite(Data, Data), addr, 1, aq, aq & rl, true)), + (HALF, _) => extend_value(is_unsigned, mem_read(ReadWrite(Data, Data), addr, 2, aq, aq & rl, true)), + (WORD, _) => extend_value(is_unsigned, mem_read(ReadWrite(Data, Data), addr, 4, aq, aq & rl, true)), + (DOUBLE, 64) => extend_value(is_unsigned, mem_read(ReadWrite(Data, Data), addr, 8, aq, aq & rl, true)), + _ => internal_error(__FILE__, __LINE__, "Unexpected AMO width") + }; + match (mval) { + MemException(e) => { handle_mem_exception(vaddr, e); RETIRE_FAIL }, + MemValue(loaded) => { + let result : xlenbits = + match op { + AMOSWAP => rs2_val, + AMOADD => rs2_val + loaded, + AMOXOR => rs2_val ^ loaded, + AMOAND => rs2_val & loaded, + AMOOR => rs2_val | loaded, + + /* These operations convert bitvectors to integer values using [un]signed, + * and back using to_bits(). + */ + AMOMIN => to_bits(sizeof(xlen), min(signed(rs2_val), signed(loaded))), + AMOMAX => to_bits(sizeof(xlen), max(signed(rs2_val), signed(loaded))), + AMOMINU => to_bits(sizeof(xlen), min(unsigned(rs2_val), unsigned(loaded))), + AMOMAXU => to_bits(sizeof(xlen), max(unsigned(rs2_val), unsigned(loaded))) + }; + let rval : xlenbits = match width { + BYTE => sign_extend(loaded[7..0]), + HALF => sign_extend(loaded[15..0]), + WORD => sign_extend(loaded[31..0]), + DOUBLE => loaded + }; + let wval : MemoryOpResult(bool) = match (width, sizeof(xlen)) { + (BYTE, _) => mem_write_value(addr, 1, result[7..0], aq & rl, rl, true), + (HALF, _) => mem_write_value(addr, 2, result[15..0], aq & rl, rl, true), + (WORD, _) => mem_write_value(addr, 4, result[31..0], aq & rl, rl, true), + (DOUBLE, 64) => mem_write_value(addr, 8, result, aq & rl, rl, true), + _ => internal_error(__FILE__, __LINE__, "Unexpected AMO width") + }; + match (wval) { + MemValue(true) => { X(rd) = rval; RETIRE_SUCCESS }, + MemValue(false) => { internal_error(__FILE__, __LINE__, "AMO got false from mem_write_value") }, + MemException(e) => { handle_mem_exception(vaddr, e); RETIRE_FAIL } + } + } + } + } + } + } + } + } + } + } else { + handle_illegal(); + RETIRE_FAIL + } + } + +# SPDX-SnippetEnd diff --git a/spec/std/isa/inst/Zaamo/amoand.w.rl.yaml b/spec/std/isa/inst/Zaamo/amoand.w.rl.yaml new file mode 100644 index 0000000000..4fc6b5778a --- /dev/null +++ b/spec/std/isa/inst/Zaamo/amoand.w.rl.yaml @@ -0,0 +1,139 @@ +# Copyright (c) Qualcomm Technologies, Inc. and/or its subsidiaries. + +# WARNING: This file is auto-generated from spec/std/isa/inst/Zaamo/amoand.SIZE.AQRL.layout# Copyright (c) Abhijit Das(Sukuna0007Abhi) +# SPDX-License-Identifier: BSD-3-Clause-Clear + +# yaml-language-server: $schema=../../../../schemas/inst_schema.json + +$schema: "inst_schema.json#" +kind: instruction +name: amoand.w.rl +long_name: Atomic fetch-and-and word (release) +description: | + Atomically with release ordering: + + * Load the word at address _xs1_ + * Write the sign-extended value into _xd_ + * AND the least-significant word of register _xs2_ to the loaded value + * Write the result to the address in _xs1_ +definedBy: Zaamo +assembly: xd, xs2, (xs1) +encoding: + match: 0110001----------010-----0101111 + variables: + - name: xs2 + location: 24-20 + - name: xs1 + location: 19-15 + - name: xd + location: 11-7 +access: + s: always + u: always + vs: always + vu: always +operation(): | + if (!implemented?(ExtensionName::A) || (MISA_CSR_IMPLEMENTED && (CSR[misa].A == 1'b0))) { + raise (ExceptionCode::IllegalInstruction, mode(), $encoding); + } + + XReg virtual_address = X[xs1]; + X[xd] = amo<32>(virtual_address, X[xs2][31:0], AmoOperation::And, 1'b0, 1'b1, $encoding); + + memory_model_release(); + +# SPDX-SnippetBegin +# SPDX-FileCopyrightText: 2017-2025 Contributors to the RISCV Sail Model +# SPDX-License-Identifier: BSD-2-Clause +sail(): | + { + if extension("A") then { + /* Get the address, X(rs1) (no offset). + * Some extensions perform additional checks on address validity. + */ + match ext_data_get_addr(rs1, zeros(), ReadWrite(Data, Data), width) { + Ext_DataAddr_Error(e) => { ext_handle_data_check_error(e); RETIRE_FAIL }, + Ext_DataAddr_OK(vaddr) => { + match translateAddr(vaddr, ReadWrite(Data, Data)) { + TR_Failure(e, _) => { handle_mem_exception(vaddr, e); RETIRE_FAIL }, + TR_Address(addr, _) => { + let eares : MemoryOpResult(unit) = match (width, sizeof(xlen)) { + (BYTE, _) => mem_write_ea(addr, 1, aq & rl, rl, true), + (HALF, _) => mem_write_ea(addr, 2, aq & rl, rl, true), + (WORD, _) => mem_write_ea(addr, 4, aq & rl, rl, true), + (DOUBLE, 64) => mem_write_ea(addr, 8, aq & rl, rl, true), + _ => internal_error(__FILE__, __LINE__, "Unexpected AMO width") + }; + let is_unsigned : bool = match op { + AMOMINU => true, + AMOMAXU => true, + _ => false + }; + let rs2_val : xlenbits = match width { + BYTE => if is_unsigned then zero_extend(X(rs2)[7..0]) else sign_extend(X(rs2)[7..0]), + HALF => if is_unsigned then zero_extend(X(rs2)[15..0]) else sign_extend(X(rs2)[15..0]), + WORD => if is_unsigned then zero_extend(X(rs2)[31..0]) else sign_extend(X(rs2)[31..0]), + DOUBLE => X(rs2) + }; + match (eares) { + MemException(e) => { handle_mem_exception(vaddr, e); RETIRE_FAIL }, + MemValue(_) => { + let mval : MemoryOpResult(xlenbits) = match (width, sizeof(xlen)) { + (BYTE, _) => extend_value(is_unsigned, mem_read(ReadWrite(Data, Data), addr, 1, aq, aq & rl, true)), + (HALF, _) => extend_value(is_unsigned, mem_read(ReadWrite(Data, Data), addr, 2, aq, aq & rl, true)), + (WORD, _) => extend_value(is_unsigned, mem_read(ReadWrite(Data, Data), addr, 4, aq, aq & rl, true)), + (DOUBLE, 64) => extend_value(is_unsigned, mem_read(ReadWrite(Data, Data), addr, 8, aq, aq & rl, true)), + _ => internal_error(__FILE__, __LINE__, "Unexpected AMO width") + }; + match (mval) { + MemException(e) => { handle_mem_exception(vaddr, e); RETIRE_FAIL }, + MemValue(loaded) => { + let result : xlenbits = + match op { + AMOSWAP => rs2_val, + AMOADD => rs2_val + loaded, + AMOXOR => rs2_val ^ loaded, + AMOAND => rs2_val & loaded, + AMOOR => rs2_val | loaded, + + /* These operations convert bitvectors to integer values using [un]signed, + * and back using to_bits(). + */ + AMOMIN => to_bits(sizeof(xlen), min(signed(rs2_val), signed(loaded))), + AMOMAX => to_bits(sizeof(xlen), max(signed(rs2_val), signed(loaded))), + AMOMINU => to_bits(sizeof(xlen), min(unsigned(rs2_val), unsigned(loaded))), + AMOMAXU => to_bits(sizeof(xlen), max(unsigned(rs2_val), unsigned(loaded))) + }; + let rval : xlenbits = match width { + BYTE => sign_extend(loaded[7..0]), + HALF => sign_extend(loaded[15..0]), + WORD => sign_extend(loaded[31..0]), + DOUBLE => loaded + }; + let wval : MemoryOpResult(bool) = match (width, sizeof(xlen)) { + (BYTE, _) => mem_write_value(addr, 1, result[7..0], aq & rl, rl, true), + (HALF, _) => mem_write_value(addr, 2, result[15..0], aq & rl, rl, true), + (WORD, _) => mem_write_value(addr, 4, result[31..0], aq & rl, rl, true), + (DOUBLE, 64) => mem_write_value(addr, 8, result, aq & rl, rl, true), + _ => internal_error(__FILE__, __LINE__, "Unexpected AMO width") + }; + match (wval) { + MemValue(true) => { X(rd) = rval; RETIRE_SUCCESS }, + MemValue(false) => { internal_error(__FILE__, __LINE__, "AMO got false from mem_write_value") }, + MemException(e) => { handle_mem_exception(vaddr, e); RETIRE_FAIL } + } + } + } + } + } + } + } + } + } + } else { + handle_illegal(); + RETIRE_FAIL + } + } + +# SPDX-SnippetEnd diff --git a/spec/std/isa/inst/Zaamo/amoand.w.yaml b/spec/std/isa/inst/Zaamo/amoand.w.yaml index aeefb40d06..a3d19e0426 100644 --- a/spec/std/isa/inst/Zaamo/amoand.w.yaml +++ b/spec/std/isa/inst/Zaamo/amoand.w.yaml @@ -1,4 +1,6 @@ # Copyright (c) Qualcomm Technologies, Inc. and/or its subsidiaries. + +# WARNING: This file is auto-generated from spec/std/isa/inst/Zaamo/amoand.SIZE.AQRL.layout# Copyright (c) Abhijit Das(Sukuna0007Abhi) # SPDX-License-Identifier: BSD-3-Clause-Clear # yaml-language-server: $schema=../../../../schemas/inst_schema.json @@ -17,12 +19,8 @@ description: | definedBy: Zaamo assembly: xd, xs2, (xs1) encoding: - match: 01100------------010-----0101111 + match: 0110000----------010-----0101111 variables: - - name: aq - location: 26 - - name: rl - location: 25 - name: xs2 location: 24-20 - name: xs1 @@ -35,15 +33,12 @@ access: vs: always vu: always operation(): | - if (implemented?(ExtensionName::A) && (CSR[misa].A == 1'b0)) { - # even though this is a memory operation, the exception occurs before that would be known, - # so mode() is the correct reporting mode rathat than effective_ldst_mode() + if (!implemented?(ExtensionName::A) || (MISA_CSR_IMPLEMENTED && (CSR[misa].A == 1'b0))) { raise (ExceptionCode::IllegalInstruction, mode(), $encoding); } XReg virtual_address = X[xs1]; - - X[xd] = amo<32>(virtual_address, X[xs2][31:0], AmoOperation::And, aq, rl, $encoding); + X[xd] = amo<32>(virtual_address, X[xs2][31:0], AmoOperation::And, 1'b0, 1'b0, $encoding); # SPDX-SnippetBegin # SPDX-FileCopyrightText: 2017-2025 Contributors to the RISCV Sail Model diff --git a/spec/std/isa/inst/Zaamo/amomax.SIZE.AQRL.layout b/spec/std/isa/inst/Zaamo/amomax.SIZE.AQRL.layout new file mode 100644 index 0000000000..5dce49efab --- /dev/null +++ b/spec/std/isa/inst/Zaamo/amomax.SIZE.AQRL.layout @@ -0,0 +1,175 @@ +# Copyright (c) Qualcomm Technologies, Inc. and/or its subsidiaries. +# Copyright (c) Abhijit Das(Sukuna0007Abhi) +# SPDX-License-Identifier: BSD-3-Clause-Clear + +# yaml-language-server: $schema=../../../../schemas/inst_schema.json +<%- + raise "'size' must be defined as 'b', 'h', 'w', or 'd'" unless %w[b h w d].include?(size) + raise "'aq' must be defined as true or false" unless [true, false].include?(aq) + raise "'rl' must be defined as true or false" unless [true, false].include?(rl) + + size_info = { + "b" => { name: "byte", bits: 8, funct3: "000", operation_bits: "8" }, + "h" => { name: "halfword", bits: 16, funct3: "001", operation_bits: "16" }, + "w" => { name: "word", bits: 32, funct3: "010", operation_bits: "32" }, + "d" => { name: "doubleword", bits: 64, funct3: "011", operation_bits: "64" } + } + + current_size = size_info[size] + + # Generate instruction name suffix based on aq/rl + aq_rl_suffix = "" + if aq && rl + aq_rl_suffix = ".aqrl" + elsif aq + aq_rl_suffix = ".aq" + elsif rl + aq_rl_suffix = ".rl" + end + + # Generate match string with fixed aq/rl bits + aq_bit = aq ? "1" : "0" + rl_bit = rl ? "1" : "0" +-%> + +$schema: "inst_schema.json#" +kind: instruction +name: amomax.<%= size %><%= aq_rl_suffix %> +long_name: Atomic MAX <%= current_size[:name] %><%= aq && rl ? " (acquire-release)" : (aq ? " (acquire)" : (rl ? " (release)" : "")) %> +description: | + Atomically<%= aq && rl ? " with acquire and release ordering" : (aq ? " with acquire ordering" : (rl ? " with release ordering" : "")) %>: + + * Load the <%= current_size[:name] %> at address _xs1_ + * Write the <%= %w[b h w].include?(size) ? "sign-extended value" : "loaded value" %> into _xd_ + * Signed compare the <%= %w[b h w].include?(size) ? "least-significant #{current_size[:name]} of register" : "value of register" %> _xs2_ to the loaded value, and select the maximum value + * Write the maximum to the address in _xs1_ +definedBy: <%= %w[b h].include?(size) ? "Zabha" : "Zaamo" %> +<%- if size == "d" -%> +base: 64 +<%- end -%> +assembly: xd, xs2, (xs1) +encoding: + match: 10100<%= aq_bit %><%= rl_bit %>----------<%= current_size[:funct3] %>-----0101111 + variables: + - name: xs2 + location: 24-20 + - name: xs1 + location: 19-15 + - name: xd + location: 11-7 +access: + s: always + u: always + vs: always + vu: always +operation(): | + if (!implemented?(ExtensionName::A) || (MISA_CSR_IMPLEMENTED && (CSR[misa].A == 1'b0))) { + raise (ExceptionCode::IllegalInstruction, mode(), $encoding); + } + +<% if aq -%> + memory_model_acquire(); + +<% end -%> + XReg virtual_address = X[xs1]; + X[xd] = amo<<%= current_size[:operation_bits] %>>(virtual_address, X[xs2]<%= %w[b h w].include?(size) ? "[#{current_size[:bits]-1}:0]" : "" %>, AmoOperation::Max, <%= aq ? "1'b1" : "1'b0" %>, <%= rl ? "1'b1" : "1'b0" %>, $encoding); +<% if rl -%> + + memory_model_release(); +<% end -%> + +# SPDX-SnippetBegin +# SPDX-FileCopyrightText: 2017-2025 Contributors to the RISCV Sail Model +# SPDX-License-Identifier: BSD-2-Clause +sail(): | + { + if extension("A") then { + /* Get the address, X(rs1) (no offset). + * Some extensions perform additional checks on address validity. + */ + match ext_data_get_addr(rs1, zeros(), ReadWrite(Data, Data), width) { + Ext_DataAddr_Error(e) => { ext_handle_data_check_error(e); RETIRE_FAIL }, + Ext_DataAddr_OK(vaddr) => { + match translateAddr(vaddr, ReadWrite(Data, Data)) { + TR_Failure(e, _) => { handle_mem_exception(vaddr, e); RETIRE_FAIL }, + TR_Address(addr, _) => { + let eares : MemoryOpResult(unit) = match (width, sizeof(xlen)) { + (BYTE, _) => mem_write_ea(addr, 1, aq & rl, rl, true), + (HALF, _) => mem_write_ea(addr, 2, aq & rl, rl, true), + (WORD, _) => mem_write_ea(addr, 4, aq & rl, rl, true), + (DOUBLE, 64) => mem_write_ea(addr, 8, aq & rl, rl, true), + _ => internal_error(__FILE__, __LINE__, "Unexpected AMO width") + }; + let is_unsigned : bool = match op { + AMOMINU => true, + AMOMAXU => true, + _ => false + }; + let rs2_val : xlenbits = match width { + BYTE => if is_unsigned then zero_extend(X(rs2)[7..0]) else sign_extend(X(rs2)[7..0]), + HALF => if is_unsigned then zero_extend(X(rs2)[15..0]) else sign_extend(X(rs2)[15..0]), + WORD => if is_unsigned then zero_extend(X(rs2)[31..0]) else sign_extend(X(rs2)[31..0]), + DOUBLE => X(rs2) + }; + match (eares) { + MemException(e) => { handle_mem_exception(vaddr, e); RETIRE_FAIL }, + MemValue(_) => { + let mval : MemoryOpResult(xlenbits) = match (width, sizeof(xlen)) { + (BYTE, _) => extend_value(is_unsigned, mem_read(ReadWrite(Data, Data), addr, 1, aq, aq & rl, true)), + (HALF, _) => extend_value(is_unsigned, mem_read(ReadWrite(Data, Data), addr, 2, aq, aq & rl, true)), + (WORD, _) => extend_value(is_unsigned, mem_read(ReadWrite(Data, Data), addr, 4, aq, aq & rl, true)), + (DOUBLE, 64) => extend_value(is_unsigned, mem_read(ReadWrite(Data, Data), addr, 8, aq, aq & rl, true)), + _ => internal_error(__FILE__, __LINE__, "Unexpected AMO width") + }; + match (mval) { + MemException(e) => { handle_mem_exception(vaddr, e); RETIRE_FAIL }, + MemValue(loaded) => { + let result : xlenbits = + match op { + AMOSWAP => rs2_val, + AMOADD => rs2_val + loaded, + AMOXOR => rs2_val ^ loaded, + AMOAND => rs2_val & loaded, + AMOOR => rs2_val | loaded, + + /* These operations convert bitvectors to integer values using [un]signed, + * and back using to_bits(). + */ + AMOMIN => to_bits(sizeof(xlen), min(signed(rs2_val), signed(loaded))), + AMOMAX => to_bits(sizeof(xlen), max(signed(rs2_val), signed(loaded))), + AMOMINU => to_bits(sizeof(xlen), min(unsigned(rs2_val), unsigned(loaded))), + AMOMAXU => to_bits(sizeof(xlen), max(unsigned(rs2_val), unsigned(loaded))) + }; + let rval : xlenbits = match width { + BYTE => sign_extend(loaded[7..0]), + HALF => sign_extend(loaded[15..0]), + WORD => sign_extend(loaded[31..0]), + DOUBLE => loaded + }; + let wval : MemoryOpResult(bool) = match (width, sizeof(xlen)) { + (BYTE, _) => mem_write_value(addr, 1, result[7..0], aq & rl, rl, true), + (HALF, _) => mem_write_value(addr, 2, result[15..0], aq & rl, rl, true), + (WORD, _) => mem_write_value(addr, 4, result[31..0], aq & rl, rl, true), + (DOUBLE, 64) => mem_write_value(addr, 8, result, aq & rl, rl, true), + _ => internal_error(__FILE__, __LINE__, "Unexpected AMO width") + }; + match (wval) { + MemValue(true) => { X(rd) = rval; RETIRE_SUCCESS }, + MemValue(false) => { internal_error(__FILE__, __LINE__, "AMO got false from mem_write_value") }, + MemException(e) => { handle_mem_exception(vaddr, e); RETIRE_FAIL } + } + } + } + } + } + } + } + } + } + } else { + handle_illegal(); + RETIRE_FAIL + } + } + +# SPDX-SnippetEnd diff --git a/spec/std/isa/inst/Zaamo/amomax.d.aq.yaml b/spec/std/isa/inst/Zaamo/amomax.d.aq.yaml new file mode 100644 index 0000000000..50ab4f4f4c --- /dev/null +++ b/spec/std/isa/inst/Zaamo/amomax.d.aq.yaml @@ -0,0 +1,140 @@ +# Copyright (c) Qualcomm Technologies, Inc. and/or its subsidiaries. + +# WARNING: This file is auto-generated from spec/std/isa/inst/Zaamo/amomax.SIZE.AQRL.layout# Copyright (c) Abhijit Das(Sukuna0007Abhi) +# SPDX-License-Identifier: BSD-3-Clause-Clear + +# yaml-language-server: $schema=../../../../schemas/inst_schema.json + +$schema: "inst_schema.json#" +kind: instruction +name: amomax.d.aq +long_name: Atomic MAX doubleword (acquire) +description: | + Atomically with acquire ordering: + + * Load the doubleword at address _xs1_ + * Write the loaded value into _xd_ + * Signed compare the value of register _xs2_ to the loaded value, and select the maximum value + * Write the maximum to the address in _xs1_ +definedBy: Zaamo +base: 64 +assembly: xd, xs2, (xs1) +encoding: + match: 1010010----------011-----0101111 + variables: + - name: xs2 + location: 24-20 + - name: xs1 + location: 19-15 + - name: xd + location: 11-7 +access: + s: always + u: always + vs: always + vu: always +operation(): | + if (!implemented?(ExtensionName::A) || (MISA_CSR_IMPLEMENTED && (CSR[misa].A == 1'b0))) { + raise (ExceptionCode::IllegalInstruction, mode(), $encoding); + } + + memory_model_acquire(); + + XReg virtual_address = X[xs1]; + X[xd] = amo<64>(virtual_address, X[xs2], AmoOperation::Max, 1'b1, 1'b0, $encoding); + +# SPDX-SnippetBegin +# SPDX-FileCopyrightText: 2017-2025 Contributors to the RISCV Sail Model +# SPDX-License-Identifier: BSD-2-Clause +sail(): | + { + if extension("A") then { + /* Get the address, X(rs1) (no offset). + * Some extensions perform additional checks on address validity. + */ + match ext_data_get_addr(rs1, zeros(), ReadWrite(Data, Data), width) { + Ext_DataAddr_Error(e) => { ext_handle_data_check_error(e); RETIRE_FAIL }, + Ext_DataAddr_OK(vaddr) => { + match translateAddr(vaddr, ReadWrite(Data, Data)) { + TR_Failure(e, _) => { handle_mem_exception(vaddr, e); RETIRE_FAIL }, + TR_Address(addr, _) => { + let eares : MemoryOpResult(unit) = match (width, sizeof(xlen)) { + (BYTE, _) => mem_write_ea(addr, 1, aq & rl, rl, true), + (HALF, _) => mem_write_ea(addr, 2, aq & rl, rl, true), + (WORD, _) => mem_write_ea(addr, 4, aq & rl, rl, true), + (DOUBLE, 64) => mem_write_ea(addr, 8, aq & rl, rl, true), + _ => internal_error(__FILE__, __LINE__, "Unexpected AMO width") + }; + let is_unsigned : bool = match op { + AMOMINU => true, + AMOMAXU => true, + _ => false + }; + let rs2_val : xlenbits = match width { + BYTE => if is_unsigned then zero_extend(X(rs2)[7..0]) else sign_extend(X(rs2)[7..0]), + HALF => if is_unsigned then zero_extend(X(rs2)[15..0]) else sign_extend(X(rs2)[15..0]), + WORD => if is_unsigned then zero_extend(X(rs2)[31..0]) else sign_extend(X(rs2)[31..0]), + DOUBLE => X(rs2) + }; + match (eares) { + MemException(e) => { handle_mem_exception(vaddr, e); RETIRE_FAIL }, + MemValue(_) => { + let mval : MemoryOpResult(xlenbits) = match (width, sizeof(xlen)) { + (BYTE, _) => extend_value(is_unsigned, mem_read(ReadWrite(Data, Data), addr, 1, aq, aq & rl, true)), + (HALF, _) => extend_value(is_unsigned, mem_read(ReadWrite(Data, Data), addr, 2, aq, aq & rl, true)), + (WORD, _) => extend_value(is_unsigned, mem_read(ReadWrite(Data, Data), addr, 4, aq, aq & rl, true)), + (DOUBLE, 64) => extend_value(is_unsigned, mem_read(ReadWrite(Data, Data), addr, 8, aq, aq & rl, true)), + _ => internal_error(__FILE__, __LINE__, "Unexpected AMO width") + }; + match (mval) { + MemException(e) => { handle_mem_exception(vaddr, e); RETIRE_FAIL }, + MemValue(loaded) => { + let result : xlenbits = + match op { + AMOSWAP => rs2_val, + AMOADD => rs2_val + loaded, + AMOXOR => rs2_val ^ loaded, + AMOAND => rs2_val & loaded, + AMOOR => rs2_val | loaded, + + /* These operations convert bitvectors to integer values using [un]signed, + * and back using to_bits(). + */ + AMOMIN => to_bits(sizeof(xlen), min(signed(rs2_val), signed(loaded))), + AMOMAX => to_bits(sizeof(xlen), max(signed(rs2_val), signed(loaded))), + AMOMINU => to_bits(sizeof(xlen), min(unsigned(rs2_val), unsigned(loaded))), + AMOMAXU => to_bits(sizeof(xlen), max(unsigned(rs2_val), unsigned(loaded))) + }; + let rval : xlenbits = match width { + BYTE => sign_extend(loaded[7..0]), + HALF => sign_extend(loaded[15..0]), + WORD => sign_extend(loaded[31..0]), + DOUBLE => loaded + }; + let wval : MemoryOpResult(bool) = match (width, sizeof(xlen)) { + (BYTE, _) => mem_write_value(addr, 1, result[7..0], aq & rl, rl, true), + (HALF, _) => mem_write_value(addr, 2, result[15..0], aq & rl, rl, true), + (WORD, _) => mem_write_value(addr, 4, result[31..0], aq & rl, rl, true), + (DOUBLE, 64) => mem_write_value(addr, 8, result, aq & rl, rl, true), + _ => internal_error(__FILE__, __LINE__, "Unexpected AMO width") + }; + match (wval) { + MemValue(true) => { X(rd) = rval; RETIRE_SUCCESS }, + MemValue(false) => { internal_error(__FILE__, __LINE__, "AMO got false from mem_write_value") }, + MemException(e) => { handle_mem_exception(vaddr, e); RETIRE_FAIL } + } + } + } + } + } + } + } + } + } + } else { + handle_illegal(); + RETIRE_FAIL + } + } + +# SPDX-SnippetEnd diff --git a/spec/std/isa/inst/Zaamo/amomax.d.aqrl.yaml b/spec/std/isa/inst/Zaamo/amomax.d.aqrl.yaml new file mode 100644 index 0000000000..c63418ffe6 --- /dev/null +++ b/spec/std/isa/inst/Zaamo/amomax.d.aqrl.yaml @@ -0,0 +1,142 @@ +# Copyright (c) Qualcomm Technologies, Inc. and/or its subsidiaries. + +# WARNING: This file is auto-generated from spec/std/isa/inst/Zaamo/amomax.SIZE.AQRL.layout# Copyright (c) Abhijit Das(Sukuna0007Abhi) +# SPDX-License-Identifier: BSD-3-Clause-Clear + +# yaml-language-server: $schema=../../../../schemas/inst_schema.json + +$schema: "inst_schema.json#" +kind: instruction +name: amomax.d.aqrl +long_name: Atomic MAX doubleword (acquire-release) +description: | + Atomically with acquire and release ordering: + + * Load the doubleword at address _xs1_ + * Write the loaded value into _xd_ + * Signed compare the value of register _xs2_ to the loaded value, and select the maximum value + * Write the maximum to the address in _xs1_ +definedBy: Zaamo +base: 64 +assembly: xd, xs2, (xs1) +encoding: + match: 1010011----------011-----0101111 + variables: + - name: xs2 + location: 24-20 + - name: xs1 + location: 19-15 + - name: xd + location: 11-7 +access: + s: always + u: always + vs: always + vu: always +operation(): | + if (!implemented?(ExtensionName::A) || (MISA_CSR_IMPLEMENTED && (CSR[misa].A == 1'b0))) { + raise (ExceptionCode::IllegalInstruction, mode(), $encoding); + } + + memory_model_acquire(); + + XReg virtual_address = X[xs1]; + X[xd] = amo<64>(virtual_address, X[xs2], AmoOperation::Max, 1'b1, 1'b1, $encoding); + + memory_model_release(); + +# SPDX-SnippetBegin +# SPDX-FileCopyrightText: 2017-2025 Contributors to the RISCV Sail Model +# SPDX-License-Identifier: BSD-2-Clause +sail(): | + { + if extension("A") then { + /* Get the address, X(rs1) (no offset). + * Some extensions perform additional checks on address validity. + */ + match ext_data_get_addr(rs1, zeros(), ReadWrite(Data, Data), width) { + Ext_DataAddr_Error(e) => { ext_handle_data_check_error(e); RETIRE_FAIL }, + Ext_DataAddr_OK(vaddr) => { + match translateAddr(vaddr, ReadWrite(Data, Data)) { + TR_Failure(e, _) => { handle_mem_exception(vaddr, e); RETIRE_FAIL }, + TR_Address(addr, _) => { + let eares : MemoryOpResult(unit) = match (width, sizeof(xlen)) { + (BYTE, _) => mem_write_ea(addr, 1, aq & rl, rl, true), + (HALF, _) => mem_write_ea(addr, 2, aq & rl, rl, true), + (WORD, _) => mem_write_ea(addr, 4, aq & rl, rl, true), + (DOUBLE, 64) => mem_write_ea(addr, 8, aq & rl, rl, true), + _ => internal_error(__FILE__, __LINE__, "Unexpected AMO width") + }; + let is_unsigned : bool = match op { + AMOMINU => true, + AMOMAXU => true, + _ => false + }; + let rs2_val : xlenbits = match width { + BYTE => if is_unsigned then zero_extend(X(rs2)[7..0]) else sign_extend(X(rs2)[7..0]), + HALF => if is_unsigned then zero_extend(X(rs2)[15..0]) else sign_extend(X(rs2)[15..0]), + WORD => if is_unsigned then zero_extend(X(rs2)[31..0]) else sign_extend(X(rs2)[31..0]), + DOUBLE => X(rs2) + }; + match (eares) { + MemException(e) => { handle_mem_exception(vaddr, e); RETIRE_FAIL }, + MemValue(_) => { + let mval : MemoryOpResult(xlenbits) = match (width, sizeof(xlen)) { + (BYTE, _) => extend_value(is_unsigned, mem_read(ReadWrite(Data, Data), addr, 1, aq, aq & rl, true)), + (HALF, _) => extend_value(is_unsigned, mem_read(ReadWrite(Data, Data), addr, 2, aq, aq & rl, true)), + (WORD, _) => extend_value(is_unsigned, mem_read(ReadWrite(Data, Data), addr, 4, aq, aq & rl, true)), + (DOUBLE, 64) => extend_value(is_unsigned, mem_read(ReadWrite(Data, Data), addr, 8, aq, aq & rl, true)), + _ => internal_error(__FILE__, __LINE__, "Unexpected AMO width") + }; + match (mval) { + MemException(e) => { handle_mem_exception(vaddr, e); RETIRE_FAIL }, + MemValue(loaded) => { + let result : xlenbits = + match op { + AMOSWAP => rs2_val, + AMOADD => rs2_val + loaded, + AMOXOR => rs2_val ^ loaded, + AMOAND => rs2_val & loaded, + AMOOR => rs2_val | loaded, + + /* These operations convert bitvectors to integer values using [un]signed, + * and back using to_bits(). + */ + AMOMIN => to_bits(sizeof(xlen), min(signed(rs2_val), signed(loaded))), + AMOMAX => to_bits(sizeof(xlen), max(signed(rs2_val), signed(loaded))), + AMOMINU => to_bits(sizeof(xlen), min(unsigned(rs2_val), unsigned(loaded))), + AMOMAXU => to_bits(sizeof(xlen), max(unsigned(rs2_val), unsigned(loaded))) + }; + let rval : xlenbits = match width { + BYTE => sign_extend(loaded[7..0]), + HALF => sign_extend(loaded[15..0]), + WORD => sign_extend(loaded[31..0]), + DOUBLE => loaded + }; + let wval : MemoryOpResult(bool) = match (width, sizeof(xlen)) { + (BYTE, _) => mem_write_value(addr, 1, result[7..0], aq & rl, rl, true), + (HALF, _) => mem_write_value(addr, 2, result[15..0], aq & rl, rl, true), + (WORD, _) => mem_write_value(addr, 4, result[31..0], aq & rl, rl, true), + (DOUBLE, 64) => mem_write_value(addr, 8, result, aq & rl, rl, true), + _ => internal_error(__FILE__, __LINE__, "Unexpected AMO width") + }; + match (wval) { + MemValue(true) => { X(rd) = rval; RETIRE_SUCCESS }, + MemValue(false) => { internal_error(__FILE__, __LINE__, "AMO got false from mem_write_value") }, + MemException(e) => { handle_mem_exception(vaddr, e); RETIRE_FAIL } + } + } + } + } + } + } + } + } + } + } else { + handle_illegal(); + RETIRE_FAIL + } + } + +# SPDX-SnippetEnd diff --git a/spec/std/isa/inst/Zaamo/amomax.d.rl.yaml b/spec/std/isa/inst/Zaamo/amomax.d.rl.yaml new file mode 100644 index 0000000000..5eac070981 --- /dev/null +++ b/spec/std/isa/inst/Zaamo/amomax.d.rl.yaml @@ -0,0 +1,140 @@ +# Copyright (c) Qualcomm Technologies, Inc. and/or its subsidiaries. + +# WARNING: This file is auto-generated from spec/std/isa/inst/Zaamo/amomax.SIZE.AQRL.layout# Copyright (c) Abhijit Das(Sukuna0007Abhi) +# SPDX-License-Identifier: BSD-3-Clause-Clear + +# yaml-language-server: $schema=../../../../schemas/inst_schema.json + +$schema: "inst_schema.json#" +kind: instruction +name: amomax.d.rl +long_name: Atomic MAX doubleword (release) +description: | + Atomically with release ordering: + + * Load the doubleword at address _xs1_ + * Write the loaded value into _xd_ + * Signed compare the value of register _xs2_ to the loaded value, and select the maximum value + * Write the maximum to the address in _xs1_ +definedBy: Zaamo +base: 64 +assembly: xd, xs2, (xs1) +encoding: + match: 1010001----------011-----0101111 + variables: + - name: xs2 + location: 24-20 + - name: xs1 + location: 19-15 + - name: xd + location: 11-7 +access: + s: always + u: always + vs: always + vu: always +operation(): | + if (!implemented?(ExtensionName::A) || (MISA_CSR_IMPLEMENTED && (CSR[misa].A == 1'b0))) { + raise (ExceptionCode::IllegalInstruction, mode(), $encoding); + } + + XReg virtual_address = X[xs1]; + X[xd] = amo<64>(virtual_address, X[xs2], AmoOperation::Max, 1'b0, 1'b1, $encoding); + + memory_model_release(); + +# SPDX-SnippetBegin +# SPDX-FileCopyrightText: 2017-2025 Contributors to the RISCV Sail Model +# SPDX-License-Identifier: BSD-2-Clause +sail(): | + { + if extension("A") then { + /* Get the address, X(rs1) (no offset). + * Some extensions perform additional checks on address validity. + */ + match ext_data_get_addr(rs1, zeros(), ReadWrite(Data, Data), width) { + Ext_DataAddr_Error(e) => { ext_handle_data_check_error(e); RETIRE_FAIL }, + Ext_DataAddr_OK(vaddr) => { + match translateAddr(vaddr, ReadWrite(Data, Data)) { + TR_Failure(e, _) => { handle_mem_exception(vaddr, e); RETIRE_FAIL }, + TR_Address(addr, _) => { + let eares : MemoryOpResult(unit) = match (width, sizeof(xlen)) { + (BYTE, _) => mem_write_ea(addr, 1, aq & rl, rl, true), + (HALF, _) => mem_write_ea(addr, 2, aq & rl, rl, true), + (WORD, _) => mem_write_ea(addr, 4, aq & rl, rl, true), + (DOUBLE, 64) => mem_write_ea(addr, 8, aq & rl, rl, true), + _ => internal_error(__FILE__, __LINE__, "Unexpected AMO width") + }; + let is_unsigned : bool = match op { + AMOMINU => true, + AMOMAXU => true, + _ => false + }; + let rs2_val : xlenbits = match width { + BYTE => if is_unsigned then zero_extend(X(rs2)[7..0]) else sign_extend(X(rs2)[7..0]), + HALF => if is_unsigned then zero_extend(X(rs2)[15..0]) else sign_extend(X(rs2)[15..0]), + WORD => if is_unsigned then zero_extend(X(rs2)[31..0]) else sign_extend(X(rs2)[31..0]), + DOUBLE => X(rs2) + }; + match (eares) { + MemException(e) => { handle_mem_exception(vaddr, e); RETIRE_FAIL }, + MemValue(_) => { + let mval : MemoryOpResult(xlenbits) = match (width, sizeof(xlen)) { + (BYTE, _) => extend_value(is_unsigned, mem_read(ReadWrite(Data, Data), addr, 1, aq, aq & rl, true)), + (HALF, _) => extend_value(is_unsigned, mem_read(ReadWrite(Data, Data), addr, 2, aq, aq & rl, true)), + (WORD, _) => extend_value(is_unsigned, mem_read(ReadWrite(Data, Data), addr, 4, aq, aq & rl, true)), + (DOUBLE, 64) => extend_value(is_unsigned, mem_read(ReadWrite(Data, Data), addr, 8, aq, aq & rl, true)), + _ => internal_error(__FILE__, __LINE__, "Unexpected AMO width") + }; + match (mval) { + MemException(e) => { handle_mem_exception(vaddr, e); RETIRE_FAIL }, + MemValue(loaded) => { + let result : xlenbits = + match op { + AMOSWAP => rs2_val, + AMOADD => rs2_val + loaded, + AMOXOR => rs2_val ^ loaded, + AMOAND => rs2_val & loaded, + AMOOR => rs2_val | loaded, + + /* These operations convert bitvectors to integer values using [un]signed, + * and back using to_bits(). + */ + AMOMIN => to_bits(sizeof(xlen), min(signed(rs2_val), signed(loaded))), + AMOMAX => to_bits(sizeof(xlen), max(signed(rs2_val), signed(loaded))), + AMOMINU => to_bits(sizeof(xlen), min(unsigned(rs2_val), unsigned(loaded))), + AMOMAXU => to_bits(sizeof(xlen), max(unsigned(rs2_val), unsigned(loaded))) + }; + let rval : xlenbits = match width { + BYTE => sign_extend(loaded[7..0]), + HALF => sign_extend(loaded[15..0]), + WORD => sign_extend(loaded[31..0]), + DOUBLE => loaded + }; + let wval : MemoryOpResult(bool) = match (width, sizeof(xlen)) { + (BYTE, _) => mem_write_value(addr, 1, result[7..0], aq & rl, rl, true), + (HALF, _) => mem_write_value(addr, 2, result[15..0], aq & rl, rl, true), + (WORD, _) => mem_write_value(addr, 4, result[31..0], aq & rl, rl, true), + (DOUBLE, 64) => mem_write_value(addr, 8, result, aq & rl, rl, true), + _ => internal_error(__FILE__, __LINE__, "Unexpected AMO width") + }; + match (wval) { + MemValue(true) => { X(rd) = rval; RETIRE_SUCCESS }, + MemValue(false) => { internal_error(__FILE__, __LINE__, "AMO got false from mem_write_value") }, + MemException(e) => { handle_mem_exception(vaddr, e); RETIRE_FAIL } + } + } + } + } + } + } + } + } + } + } else { + handle_illegal(); + RETIRE_FAIL + } + } + +# SPDX-SnippetEnd diff --git a/spec/std/isa/inst/Zaamo/amomax.d.yaml b/spec/std/isa/inst/Zaamo/amomax.d.yaml index 6e832c305c..e8542ce159 100644 --- a/spec/std/isa/inst/Zaamo/amomax.d.yaml +++ b/spec/std/isa/inst/Zaamo/amomax.d.yaml @@ -1,4 +1,6 @@ # Copyright (c) Qualcomm Technologies, Inc. and/or its subsidiaries. + +# WARNING: This file is auto-generated from spec/std/isa/inst/Zaamo/amomax.SIZE.AQRL.layout# Copyright (c) Abhijit Das(Sukuna0007Abhi) # SPDX-License-Identifier: BSD-3-Clause-Clear # yaml-language-server: $schema=../../../../schemas/inst_schema.json @@ -18,12 +20,8 @@ definedBy: Zaamo base: 64 assembly: xd, xs2, (xs1) encoding: - match: 10100------------011-----0101111 + match: 1010000----------011-----0101111 variables: - - name: aq - location: 26 - - name: rl - location: 25 - name: xs2 location: 24-20 - name: xs1 @@ -36,15 +34,12 @@ access: vs: always vu: always operation(): | - if (implemented?(ExtensionName::A) && (CSR[misa].A == 1'b0)) { - # even though this is a memory operation, the exception occurs before that would be known, - # so mode() is the correct reporting mode rathat than effective_ldst_mode() + if (!implemented?(ExtensionName::A) || (MISA_CSR_IMPLEMENTED && (CSR[misa].A == 1'b0))) { raise (ExceptionCode::IllegalInstruction, mode(), $encoding); } XReg virtual_address = X[xs1]; - - X[xd] = amo<64>(virtual_address, X[xs2], AmoOperation::Max, aq, rl, $encoding); + X[xd] = amo<64>(virtual_address, X[xs2], AmoOperation::Max, 1'b0, 1'b0, $encoding); # SPDX-SnippetBegin # SPDX-FileCopyrightText: 2017-2025 Contributors to the RISCV Sail Model diff --git a/spec/std/isa/inst/Zaamo/amomax.w.aq.yaml b/spec/std/isa/inst/Zaamo/amomax.w.aq.yaml new file mode 100644 index 0000000000..9f203a8de8 --- /dev/null +++ b/spec/std/isa/inst/Zaamo/amomax.w.aq.yaml @@ -0,0 +1,139 @@ +# Copyright (c) Qualcomm Technologies, Inc. and/or its subsidiaries. + +# WARNING: This file is auto-generated from spec/std/isa/inst/Zaamo/amomax.SIZE.AQRL.layout# Copyright (c) Abhijit Das(Sukuna0007Abhi) +# SPDX-License-Identifier: BSD-3-Clause-Clear + +# yaml-language-server: $schema=../../../../schemas/inst_schema.json + +$schema: "inst_schema.json#" +kind: instruction +name: amomax.w.aq +long_name: Atomic MAX word (acquire) +description: | + Atomically with acquire ordering: + + * Load the word at address _xs1_ + * Write the sign-extended value into _xd_ + * Signed compare the least-significant word of register _xs2_ to the loaded value, and select the maximum value + * Write the maximum to the address in _xs1_ +definedBy: Zaamo +assembly: xd, xs2, (xs1) +encoding: + match: 1010010----------010-----0101111 + variables: + - name: xs2 + location: 24-20 + - name: xs1 + location: 19-15 + - name: xd + location: 11-7 +access: + s: always + u: always + vs: always + vu: always +operation(): | + if (!implemented?(ExtensionName::A) || (MISA_CSR_IMPLEMENTED && (CSR[misa].A == 1'b0))) { + raise (ExceptionCode::IllegalInstruction, mode(), $encoding); + } + + memory_model_acquire(); + + XReg virtual_address = X[xs1]; + X[xd] = amo<32>(virtual_address, X[xs2][31:0], AmoOperation::Max, 1'b1, 1'b0, $encoding); + +# SPDX-SnippetBegin +# SPDX-FileCopyrightText: 2017-2025 Contributors to the RISCV Sail Model +# SPDX-License-Identifier: BSD-2-Clause +sail(): | + { + if extension("A") then { + /* Get the address, X(rs1) (no offset). + * Some extensions perform additional checks on address validity. + */ + match ext_data_get_addr(rs1, zeros(), ReadWrite(Data, Data), width) { + Ext_DataAddr_Error(e) => { ext_handle_data_check_error(e); RETIRE_FAIL }, + Ext_DataAddr_OK(vaddr) => { + match translateAddr(vaddr, ReadWrite(Data, Data)) { + TR_Failure(e, _) => { handle_mem_exception(vaddr, e); RETIRE_FAIL }, + TR_Address(addr, _) => { + let eares : MemoryOpResult(unit) = match (width, sizeof(xlen)) { + (BYTE, _) => mem_write_ea(addr, 1, aq & rl, rl, true), + (HALF, _) => mem_write_ea(addr, 2, aq & rl, rl, true), + (WORD, _) => mem_write_ea(addr, 4, aq & rl, rl, true), + (DOUBLE, 64) => mem_write_ea(addr, 8, aq & rl, rl, true), + _ => internal_error(__FILE__, __LINE__, "Unexpected AMO width") + }; + let is_unsigned : bool = match op { + AMOMINU => true, + AMOMAXU => true, + _ => false + }; + let rs2_val : xlenbits = match width { + BYTE => if is_unsigned then zero_extend(X(rs2)[7..0]) else sign_extend(X(rs2)[7..0]), + HALF => if is_unsigned then zero_extend(X(rs2)[15..0]) else sign_extend(X(rs2)[15..0]), + WORD => if is_unsigned then zero_extend(X(rs2)[31..0]) else sign_extend(X(rs2)[31..0]), + DOUBLE => X(rs2) + }; + match (eares) { + MemException(e) => { handle_mem_exception(vaddr, e); RETIRE_FAIL }, + MemValue(_) => { + let mval : MemoryOpResult(xlenbits) = match (width, sizeof(xlen)) { + (BYTE, _) => extend_value(is_unsigned, mem_read(ReadWrite(Data, Data), addr, 1, aq, aq & rl, true)), + (HALF, _) => extend_value(is_unsigned, mem_read(ReadWrite(Data, Data), addr, 2, aq, aq & rl, true)), + (WORD, _) => extend_value(is_unsigned, mem_read(ReadWrite(Data, Data), addr, 4, aq, aq & rl, true)), + (DOUBLE, 64) => extend_value(is_unsigned, mem_read(ReadWrite(Data, Data), addr, 8, aq, aq & rl, true)), + _ => internal_error(__FILE__, __LINE__, "Unexpected AMO width") + }; + match (mval) { + MemException(e) => { handle_mem_exception(vaddr, e); RETIRE_FAIL }, + MemValue(loaded) => { + let result : xlenbits = + match op { + AMOSWAP => rs2_val, + AMOADD => rs2_val + loaded, + AMOXOR => rs2_val ^ loaded, + AMOAND => rs2_val & loaded, + AMOOR => rs2_val | loaded, + + /* These operations convert bitvectors to integer values using [un]signed, + * and back using to_bits(). + */ + AMOMIN => to_bits(sizeof(xlen), min(signed(rs2_val), signed(loaded))), + AMOMAX => to_bits(sizeof(xlen), max(signed(rs2_val), signed(loaded))), + AMOMINU => to_bits(sizeof(xlen), min(unsigned(rs2_val), unsigned(loaded))), + AMOMAXU => to_bits(sizeof(xlen), max(unsigned(rs2_val), unsigned(loaded))) + }; + let rval : xlenbits = match width { + BYTE => sign_extend(loaded[7..0]), + HALF => sign_extend(loaded[15..0]), + WORD => sign_extend(loaded[31..0]), + DOUBLE => loaded + }; + let wval : MemoryOpResult(bool) = match (width, sizeof(xlen)) { + (BYTE, _) => mem_write_value(addr, 1, result[7..0], aq & rl, rl, true), + (HALF, _) => mem_write_value(addr, 2, result[15..0], aq & rl, rl, true), + (WORD, _) => mem_write_value(addr, 4, result[31..0], aq & rl, rl, true), + (DOUBLE, 64) => mem_write_value(addr, 8, result, aq & rl, rl, true), + _ => internal_error(__FILE__, __LINE__, "Unexpected AMO width") + }; + match (wval) { + MemValue(true) => { X(rd) = rval; RETIRE_SUCCESS }, + MemValue(false) => { internal_error(__FILE__, __LINE__, "AMO got false from mem_write_value") }, + MemException(e) => { handle_mem_exception(vaddr, e); RETIRE_FAIL } + } + } + } + } + } + } + } + } + } + } else { + handle_illegal(); + RETIRE_FAIL + } + } + +# SPDX-SnippetEnd diff --git a/spec/std/isa/inst/Zaamo/amomax.w.aqrl.yaml b/spec/std/isa/inst/Zaamo/amomax.w.aqrl.yaml new file mode 100644 index 0000000000..a1b4ea304a --- /dev/null +++ b/spec/std/isa/inst/Zaamo/amomax.w.aqrl.yaml @@ -0,0 +1,141 @@ +# Copyright (c) Qualcomm Technologies, Inc. and/or its subsidiaries. + +# WARNING: This file is auto-generated from spec/std/isa/inst/Zaamo/amomax.SIZE.AQRL.layout# Copyright (c) Abhijit Das(Sukuna0007Abhi) +# SPDX-License-Identifier: BSD-3-Clause-Clear + +# yaml-language-server: $schema=../../../../schemas/inst_schema.json + +$schema: "inst_schema.json#" +kind: instruction +name: amomax.w.aqrl +long_name: Atomic MAX word (acquire-release) +description: | + Atomically with acquire and release ordering: + + * Load the word at address _xs1_ + * Write the sign-extended value into _xd_ + * Signed compare the least-significant word of register _xs2_ to the loaded value, and select the maximum value + * Write the maximum to the address in _xs1_ +definedBy: Zaamo +assembly: xd, xs2, (xs1) +encoding: + match: 1010011----------010-----0101111 + variables: + - name: xs2 + location: 24-20 + - name: xs1 + location: 19-15 + - name: xd + location: 11-7 +access: + s: always + u: always + vs: always + vu: always +operation(): | + if (!implemented?(ExtensionName::A) || (MISA_CSR_IMPLEMENTED && (CSR[misa].A == 1'b0))) { + raise (ExceptionCode::IllegalInstruction, mode(), $encoding); + } + + memory_model_acquire(); + + XReg virtual_address = X[xs1]; + X[xd] = amo<32>(virtual_address, X[xs2][31:0], AmoOperation::Max, 1'b1, 1'b1, $encoding); + + memory_model_release(); + +# SPDX-SnippetBegin +# SPDX-FileCopyrightText: 2017-2025 Contributors to the RISCV Sail Model +# SPDX-License-Identifier: BSD-2-Clause +sail(): | + { + if extension("A") then { + /* Get the address, X(rs1) (no offset). + * Some extensions perform additional checks on address validity. + */ + match ext_data_get_addr(rs1, zeros(), ReadWrite(Data, Data), width) { + Ext_DataAddr_Error(e) => { ext_handle_data_check_error(e); RETIRE_FAIL }, + Ext_DataAddr_OK(vaddr) => { + match translateAddr(vaddr, ReadWrite(Data, Data)) { + TR_Failure(e, _) => { handle_mem_exception(vaddr, e); RETIRE_FAIL }, + TR_Address(addr, _) => { + let eares : MemoryOpResult(unit) = match (width, sizeof(xlen)) { + (BYTE, _) => mem_write_ea(addr, 1, aq & rl, rl, true), + (HALF, _) => mem_write_ea(addr, 2, aq & rl, rl, true), + (WORD, _) => mem_write_ea(addr, 4, aq & rl, rl, true), + (DOUBLE, 64) => mem_write_ea(addr, 8, aq & rl, rl, true), + _ => internal_error(__FILE__, __LINE__, "Unexpected AMO width") + }; + let is_unsigned : bool = match op { + AMOMINU => true, + AMOMAXU => true, + _ => false + }; + let rs2_val : xlenbits = match width { + BYTE => if is_unsigned then zero_extend(X(rs2)[7..0]) else sign_extend(X(rs2)[7..0]), + HALF => if is_unsigned then zero_extend(X(rs2)[15..0]) else sign_extend(X(rs2)[15..0]), + WORD => if is_unsigned then zero_extend(X(rs2)[31..0]) else sign_extend(X(rs2)[31..0]), + DOUBLE => X(rs2) + }; + match (eares) { + MemException(e) => { handle_mem_exception(vaddr, e); RETIRE_FAIL }, + MemValue(_) => { + let mval : MemoryOpResult(xlenbits) = match (width, sizeof(xlen)) { + (BYTE, _) => extend_value(is_unsigned, mem_read(ReadWrite(Data, Data), addr, 1, aq, aq & rl, true)), + (HALF, _) => extend_value(is_unsigned, mem_read(ReadWrite(Data, Data), addr, 2, aq, aq & rl, true)), + (WORD, _) => extend_value(is_unsigned, mem_read(ReadWrite(Data, Data), addr, 4, aq, aq & rl, true)), + (DOUBLE, 64) => extend_value(is_unsigned, mem_read(ReadWrite(Data, Data), addr, 8, aq, aq & rl, true)), + _ => internal_error(__FILE__, __LINE__, "Unexpected AMO width") + }; + match (mval) { + MemException(e) => { handle_mem_exception(vaddr, e); RETIRE_FAIL }, + MemValue(loaded) => { + let result : xlenbits = + match op { + AMOSWAP => rs2_val, + AMOADD => rs2_val + loaded, + AMOXOR => rs2_val ^ loaded, + AMOAND => rs2_val & loaded, + AMOOR => rs2_val | loaded, + + /* These operations convert bitvectors to integer values using [un]signed, + * and back using to_bits(). + */ + AMOMIN => to_bits(sizeof(xlen), min(signed(rs2_val), signed(loaded))), + AMOMAX => to_bits(sizeof(xlen), max(signed(rs2_val), signed(loaded))), + AMOMINU => to_bits(sizeof(xlen), min(unsigned(rs2_val), unsigned(loaded))), + AMOMAXU => to_bits(sizeof(xlen), max(unsigned(rs2_val), unsigned(loaded))) + }; + let rval : xlenbits = match width { + BYTE => sign_extend(loaded[7..0]), + HALF => sign_extend(loaded[15..0]), + WORD => sign_extend(loaded[31..0]), + DOUBLE => loaded + }; + let wval : MemoryOpResult(bool) = match (width, sizeof(xlen)) { + (BYTE, _) => mem_write_value(addr, 1, result[7..0], aq & rl, rl, true), + (HALF, _) => mem_write_value(addr, 2, result[15..0], aq & rl, rl, true), + (WORD, _) => mem_write_value(addr, 4, result[31..0], aq & rl, rl, true), + (DOUBLE, 64) => mem_write_value(addr, 8, result, aq & rl, rl, true), + _ => internal_error(__FILE__, __LINE__, "Unexpected AMO width") + }; + match (wval) { + MemValue(true) => { X(rd) = rval; RETIRE_SUCCESS }, + MemValue(false) => { internal_error(__FILE__, __LINE__, "AMO got false from mem_write_value") }, + MemException(e) => { handle_mem_exception(vaddr, e); RETIRE_FAIL } + } + } + } + } + } + } + } + } + } + } else { + handle_illegal(); + RETIRE_FAIL + } + } + +# SPDX-SnippetEnd diff --git a/spec/std/isa/inst/Zaamo/amomax.w.rl.yaml b/spec/std/isa/inst/Zaamo/amomax.w.rl.yaml new file mode 100644 index 0000000000..ca46449dbb --- /dev/null +++ b/spec/std/isa/inst/Zaamo/amomax.w.rl.yaml @@ -0,0 +1,139 @@ +# Copyright (c) Qualcomm Technologies, Inc. and/or its subsidiaries. + +# WARNING: This file is auto-generated from spec/std/isa/inst/Zaamo/amomax.SIZE.AQRL.layout# Copyright (c) Abhijit Das(Sukuna0007Abhi) +# SPDX-License-Identifier: BSD-3-Clause-Clear + +# yaml-language-server: $schema=../../../../schemas/inst_schema.json + +$schema: "inst_schema.json#" +kind: instruction +name: amomax.w.rl +long_name: Atomic MAX word (release) +description: | + Atomically with release ordering: + + * Load the word at address _xs1_ + * Write the sign-extended value into _xd_ + * Signed compare the least-significant word of register _xs2_ to the loaded value, and select the maximum value + * Write the maximum to the address in _xs1_ +definedBy: Zaamo +assembly: xd, xs2, (xs1) +encoding: + match: 1010001----------010-----0101111 + variables: + - name: xs2 + location: 24-20 + - name: xs1 + location: 19-15 + - name: xd + location: 11-7 +access: + s: always + u: always + vs: always + vu: always +operation(): | + if (!implemented?(ExtensionName::A) || (MISA_CSR_IMPLEMENTED && (CSR[misa].A == 1'b0))) { + raise (ExceptionCode::IllegalInstruction, mode(), $encoding); + } + + XReg virtual_address = X[xs1]; + X[xd] = amo<32>(virtual_address, X[xs2][31:0], AmoOperation::Max, 1'b0, 1'b1, $encoding); + + memory_model_release(); + +# SPDX-SnippetBegin +# SPDX-FileCopyrightText: 2017-2025 Contributors to the RISCV Sail Model +# SPDX-License-Identifier: BSD-2-Clause +sail(): | + { + if extension("A") then { + /* Get the address, X(rs1) (no offset). + * Some extensions perform additional checks on address validity. + */ + match ext_data_get_addr(rs1, zeros(), ReadWrite(Data, Data), width) { + Ext_DataAddr_Error(e) => { ext_handle_data_check_error(e); RETIRE_FAIL }, + Ext_DataAddr_OK(vaddr) => { + match translateAddr(vaddr, ReadWrite(Data, Data)) { + TR_Failure(e, _) => { handle_mem_exception(vaddr, e); RETIRE_FAIL }, + TR_Address(addr, _) => { + let eares : MemoryOpResult(unit) = match (width, sizeof(xlen)) { + (BYTE, _) => mem_write_ea(addr, 1, aq & rl, rl, true), + (HALF, _) => mem_write_ea(addr, 2, aq & rl, rl, true), + (WORD, _) => mem_write_ea(addr, 4, aq & rl, rl, true), + (DOUBLE, 64) => mem_write_ea(addr, 8, aq & rl, rl, true), + _ => internal_error(__FILE__, __LINE__, "Unexpected AMO width") + }; + let is_unsigned : bool = match op { + AMOMINU => true, + AMOMAXU => true, + _ => false + }; + let rs2_val : xlenbits = match width { + BYTE => if is_unsigned then zero_extend(X(rs2)[7..0]) else sign_extend(X(rs2)[7..0]), + HALF => if is_unsigned then zero_extend(X(rs2)[15..0]) else sign_extend(X(rs2)[15..0]), + WORD => if is_unsigned then zero_extend(X(rs2)[31..0]) else sign_extend(X(rs2)[31..0]), + DOUBLE => X(rs2) + }; + match (eares) { + MemException(e) => { handle_mem_exception(vaddr, e); RETIRE_FAIL }, + MemValue(_) => { + let mval : MemoryOpResult(xlenbits) = match (width, sizeof(xlen)) { + (BYTE, _) => extend_value(is_unsigned, mem_read(ReadWrite(Data, Data), addr, 1, aq, aq & rl, true)), + (HALF, _) => extend_value(is_unsigned, mem_read(ReadWrite(Data, Data), addr, 2, aq, aq & rl, true)), + (WORD, _) => extend_value(is_unsigned, mem_read(ReadWrite(Data, Data), addr, 4, aq, aq & rl, true)), + (DOUBLE, 64) => extend_value(is_unsigned, mem_read(ReadWrite(Data, Data), addr, 8, aq, aq & rl, true)), + _ => internal_error(__FILE__, __LINE__, "Unexpected AMO width") + }; + match (mval) { + MemException(e) => { handle_mem_exception(vaddr, e); RETIRE_FAIL }, + MemValue(loaded) => { + let result : xlenbits = + match op { + AMOSWAP => rs2_val, + AMOADD => rs2_val + loaded, + AMOXOR => rs2_val ^ loaded, + AMOAND => rs2_val & loaded, + AMOOR => rs2_val | loaded, + + /* These operations convert bitvectors to integer values using [un]signed, + * and back using to_bits(). + */ + AMOMIN => to_bits(sizeof(xlen), min(signed(rs2_val), signed(loaded))), + AMOMAX => to_bits(sizeof(xlen), max(signed(rs2_val), signed(loaded))), + AMOMINU => to_bits(sizeof(xlen), min(unsigned(rs2_val), unsigned(loaded))), + AMOMAXU => to_bits(sizeof(xlen), max(unsigned(rs2_val), unsigned(loaded))) + }; + let rval : xlenbits = match width { + BYTE => sign_extend(loaded[7..0]), + HALF => sign_extend(loaded[15..0]), + WORD => sign_extend(loaded[31..0]), + DOUBLE => loaded + }; + let wval : MemoryOpResult(bool) = match (width, sizeof(xlen)) { + (BYTE, _) => mem_write_value(addr, 1, result[7..0], aq & rl, rl, true), + (HALF, _) => mem_write_value(addr, 2, result[15..0], aq & rl, rl, true), + (WORD, _) => mem_write_value(addr, 4, result[31..0], aq & rl, rl, true), + (DOUBLE, 64) => mem_write_value(addr, 8, result, aq & rl, rl, true), + _ => internal_error(__FILE__, __LINE__, "Unexpected AMO width") + }; + match (wval) { + MemValue(true) => { X(rd) = rval; RETIRE_SUCCESS }, + MemValue(false) => { internal_error(__FILE__, __LINE__, "AMO got false from mem_write_value") }, + MemException(e) => { handle_mem_exception(vaddr, e); RETIRE_FAIL } + } + } + } + } + } + } + } + } + } + } else { + handle_illegal(); + RETIRE_FAIL + } + } + +# SPDX-SnippetEnd diff --git a/spec/std/isa/inst/Zaamo/amomax.w.yaml b/spec/std/isa/inst/Zaamo/amomax.w.yaml index d3b2f6807d..892cac3f86 100644 --- a/spec/std/isa/inst/Zaamo/amomax.w.yaml +++ b/spec/std/isa/inst/Zaamo/amomax.w.yaml @@ -1,4 +1,6 @@ # Copyright (c) Qualcomm Technologies, Inc. and/or its subsidiaries. + +# WARNING: This file is auto-generated from spec/std/isa/inst/Zaamo/amomax.SIZE.AQRL.layout# Copyright (c) Abhijit Das(Sukuna0007Abhi) # SPDX-License-Identifier: BSD-3-Clause-Clear # yaml-language-server: $schema=../../../../schemas/inst_schema.json @@ -17,12 +19,8 @@ description: | definedBy: Zaamo assembly: xd, xs2, (xs1) encoding: - match: 10100------------010-----0101111 + match: 1010000----------010-----0101111 variables: - - name: aq - location: 26 - - name: rl - location: 25 - name: xs2 location: 24-20 - name: xs1 @@ -35,15 +33,12 @@ access: vs: always vu: always operation(): | - if (implemented?(ExtensionName::A) && (CSR[misa].A == 1'b0)) { - # even though this is a memory operation, the exception occurs before that would be known, - # so mode() is the correct reporting mode rathat than effective_ldst_mode() + if (!implemented?(ExtensionName::A) || (MISA_CSR_IMPLEMENTED && (CSR[misa].A == 1'b0))) { raise (ExceptionCode::IllegalInstruction, mode(), $encoding); } XReg virtual_address = X[xs1]; - - X[xd] = amo<32>(virtual_address, X[xs2][31:0], AmoOperation::Max, aq, rl, $encoding); + X[xd] = amo<32>(virtual_address, X[xs2][31:0], AmoOperation::Max, 1'b0, 1'b0, $encoding); # SPDX-SnippetBegin # SPDX-FileCopyrightText: 2017-2025 Contributors to the RISCV Sail Model diff --git a/spec/std/isa/inst/Zaamo/amomaxu.SIZE.AQRL.layout b/spec/std/isa/inst/Zaamo/amomaxu.SIZE.AQRL.layout new file mode 100644 index 0000000000..ca486d630f --- /dev/null +++ b/spec/std/isa/inst/Zaamo/amomaxu.SIZE.AQRL.layout @@ -0,0 +1,175 @@ +# Copyright (c) Qualcomm Technologies, Inc. and/or its subsidiaries. +# Copyright (c) Abhijit Das(Sukuna0007Abhi) +# SPDX-License-Identifier: BSD-3-Clause-Clear + +# yaml-language-server: $schema=../../../../schemas/inst_schema.json +<%- + raise "'size' must be defined as 'b', 'h', 'w', or 'd'" unless %w[b h w d].include?(size) + raise "'aq' must be defined as true or false" unless [true, false].include?(aq) + raise "'rl' must be defined as true or false" unless [true, false].include?(rl) + + size_info = { + "b" => { name: "byte", bits: 8, funct3: "000", operation_bits: "8" }, + "h" => { name: "halfword", bits: 16, funct3: "001", operation_bits: "16" }, + "w" => { name: "word", bits: 32, funct3: "010", operation_bits: "32" }, + "d" => { name: "doubleword", bits: 64, funct3: "011", operation_bits: "64" } + } + + current_size = size_info[size] + + # Generate instruction name suffix based on aq/rl + aq_rl_suffix = "" + if aq && rl + aq_rl_suffix = ".aqrl" + elsif aq + aq_rl_suffix = ".aq" + elsif rl + aq_rl_suffix = ".rl" + end + + # Generate match string with fixed aq/rl bits + aq_bit = aq ? "1" : "0" + rl_bit = rl ? "1" : "0" +-%> + +$schema: "inst_schema.json#" +kind: instruction +name: amomaxu.<%= size %><%= aq_rl_suffix %> +long_name: Atomic MAX unsigned <%= current_size[:name] %><%= aq && rl ? " (acquire-release)" : (aq ? " (acquire)" : (rl ? " (release)" : "")) %> +description: | + Atomically<%= aq && rl ? " with acquire and release ordering" : (aq ? " with acquire ordering" : (rl ? " with release ordering" : "")) %>: + + * Load the <%= current_size[:name] %> at address _xs1_ + * Write the <%= %w[b h w].include?(size) ? "sign-extended value" : "loaded value" %> into _xd_ + * Unsigned compare the <%= %w[b h w].include?(size) ? "least-significant #{current_size[:name]} of register" : "value of register" %> _xs2_ to the loaded value, and select the maximum value + * Write the maximum to the address in _xs1_ +definedBy: <%= %w[b h].include?(size) ? "Zabha" : "Zaamo" %> +<%- if size == "d" -%> +base: 64 +<%- end -%> +assembly: xd, xs2, (xs1) +encoding: + match: 11100<%= aq_bit %><%= rl_bit %>----------<%= current_size[:funct3] %>-----0101111 + variables: + - name: xs2 + location: 24-20 + - name: xs1 + location: 19-15 + - name: xd + location: 11-7 +access: + s: always + u: always + vs: always + vu: always +operation(): | + if (!implemented?(ExtensionName::A) || (MISA_CSR_IMPLEMENTED && (CSR[misa].A == 1'b0))) { + raise (ExceptionCode::IllegalInstruction, mode(), $encoding); + } + +<% if aq -%> + memory_model_acquire(); + +<% end -%> + XReg virtual_address = X[xs1]; + X[xd] = amo<<%= current_size[:operation_bits] %>>(virtual_address, X[xs2]<%= %w[b h w].include?(size) ? "[#{current_size[:bits]-1}:0]" : "" %>, AmoOperation::Maxu, <%= aq ? "1'b1" : "1'b0" %>, <%= rl ? "1'b1" : "1'b0" %>, $encoding); +<% if rl -%> + + memory_model_release(); +<% end -%> + +# SPDX-SnippetBegin +# SPDX-FileCopyrightText: 2017-2025 Contributors to the RISCV Sail Model +# SPDX-License-Identifier: BSD-2-Clause +sail(): | + { + if extension("A") then { + /* Get the address, X(rs1) (no offset). + * Some extensions perform additional checks on address validity. + */ + match ext_data_get_addr(rs1, zeros(), ReadWrite(Data, Data), width) { + Ext_DataAddr_Error(e) => { ext_handle_data_check_error(e); RETIRE_FAIL }, + Ext_DataAddr_OK(vaddr) => { + match translateAddr(vaddr, ReadWrite(Data, Data)) { + TR_Failure(e, _) => { handle_mem_exception(vaddr, e); RETIRE_FAIL }, + TR_Address(addr, _) => { + let eares : MemoryOpResult(unit) = match (width, sizeof(xlen)) { + (BYTE, _) => mem_write_ea(addr, 1, <%= aq ? "true" : "false" %> & <%= rl ? "true" : "false" %>, <%= rl ? "true" : "false" %>, true), + (HALF, _) => mem_write_ea(addr, 2, <%= aq ? "true" : "false" %> & <%= rl ? "true" : "false" %>, <%= rl ? "true" : "false" %>, true), + (WORD, _) => mem_write_ea(addr, 4, <%= aq ? "true" : "false" %> & <%= rl ? "true" : "false" %>, <%= rl ? "true" : "false" %>, true), + (DOUBLE, 64) => mem_write_ea(addr, 8, <%= aq ? "true" : "false" %> & <%= rl ? "true" : "false" %>, <%= rl ? "true" : "false" %>, true), + _ => internal_error(__FILE__, __LINE__, "Unexpected AMO width") + }; + let is_unsigned : bool = match op { + AMOMINU => true, + AMOMAXU => true, + _ => false + }; + let xs2_val : xlenbits = match width { + BYTE => if is_unsigned then zero_extend(X(rs2)[7..0]) else sign_extend(X(rs2)[7..0]), + HALF => if is_unsigned then zero_extend(X(rs2)[15..0]) else sign_extend(X(rs2)[15..0]), + WORD => if is_unsigned then zero_extend(X(rs2)[31..0]) else sign_extend(X(rs2)[31..0]), + DOUBLE => X(rs2) + }; + match (eares) { + MemException(e) => { handle_mem_exception(vaddr, e); RETIRE_FAIL }, + MemValue(_) => { + let mval : MemoryOpResult(xlenbits) = match (width, sizeof(xlen)) { + (BYTE, _) => extend_value(is_unsigned, mem_read(ReadWrite(Data, Data), addr, 1, <%= aq ? "true" : "false" %>, <%= aq ? "true" : "false" %> & <%= rl ? "true" : "false" %>, true)), + (HALF, _) => extend_value(is_unsigned, mem_read(ReadWrite(Data, Data), addr, 2, <%= aq ? "true" : "false" %>, <%= aq ? "true" : "false" %> & <%= rl ? "true" : "false" %>, true)), + (WORD, _) => extend_value(is_unsigned, mem_read(ReadWrite(Data, Data), addr, 4, <%= aq ? "true" : "false" %>, <%= aq ? "true" : "false" %> & <%= rl ? "true" : "false" %>, true)), + (DOUBLE, 64) => extend_value(is_unsigned, mem_read(ReadWrite(Data, Data), addr, 8, <%= aq ? "true" : "false" %>, <%= aq ? "true" : "false" %> & <%= rl ? "true" : "false" %>, true)), + _ => internal_error(__FILE__, __LINE__, "Unexpected AMO width") + }; + match (mval) { + MemException(e) => { handle_mem_exception(vaddr, e); RETIRE_FAIL }, + MemValue(loaded) => { + let result : xlenbits = + match op { + AMOSWAP => xs2_val, + AMOADD => xs2_val + loaded, + AMOXOR => xs2_val ^ loaded, + AMOAND => xs2_val & loaded, + AMOOR => xs2_val | loaded, + + /* These operations convert bitvectors to integer values using [un]signed, + * and back using to_bits(). + */ + AMOMIN => to_bits(sizeof(xlen), min(signed(xs2_val), signed(loaded))), + AMOMAX => to_bits(sizeof(xlen), max(signed(xs2_val), signed(loaded))), + AMOMINU => to_bits(sizeof(xlen), min(unsigned(xs2_val), unsigned(loaded))), + AMOMAXU => to_bits(sizeof(xlen), max(unsigned(xs2_val), unsigned(loaded))) + }; + let rval : xlenbits = match width { + BYTE => sign_extend(loaded[7..0]), + HALF => sign_extend(loaded[15..0]), + WORD => sign_extend(loaded[31..0]), + DOUBLE => loaded + }; + let wval : MemoryOpResult(bool) = match (width, sizeof(xlen)) { + (BYTE, _) => mem_write_value(addr, 1, result[7..0], <%= aq ? "true" : "false" %> & <%= rl ? "true" : "false" %>, <%= rl ? "true" : "false" %>, true), + (HALF, _) => mem_write_value(addr, 2, result[15..0], <%= aq ? "true" : "false" %> & <%= rl ? "true" : "false" %>, <%= rl ? "true" : "false" %>, true), + (WORD, _) => mem_write_value(addr, 4, result[31..0], <%= aq ? "true" : "false" %> & <%= rl ? "true" : "false" %>, <%= rl ? "true" : "false" %>, true), + (DOUBLE, 64) => mem_write_value(addr, 8, result, <%= aq ? "true" : "false" %> & <%= rl ? "true" : "false" %>, <%= rl ? "true" : "false" %>, true), + _ => internal_error(__FILE__, __LINE__, "Unexpected AMO width") + }; + match (wval) { + MemValue(true) => { X(rd) = rval; RETIRE_SUCCESS }, + MemValue(false) => { internal_error(__FILE__, __LINE__, "AMO got false from mem_write_value") }, + MemException(e) => { handle_mem_exception(vaddr, e); RETIRE_FAIL } + } + } + } + } + } + } + } + } + } + } else { + handle_illegal(); + RETIRE_FAIL + } + } + +# SPDX-SnippetEnd diff --git a/spec/std/isa/inst/Zaamo/amomaxu.d.aq.yaml b/spec/std/isa/inst/Zaamo/amomaxu.d.aq.yaml new file mode 100644 index 0000000000..416e0227a0 --- /dev/null +++ b/spec/std/isa/inst/Zaamo/amomaxu.d.aq.yaml @@ -0,0 +1,140 @@ +# Copyright (c) Qualcomm Technologies, Inc. and/or its subsidiaries. + +# WARNING: This file is auto-generated from spec/std/isa/inst/Zaamo/amomaxu.SIZE.AQRL.layout# Copyright (c) Abhijit Das(Sukuna0007Abhi) +# SPDX-License-Identifier: BSD-3-Clause-Clear + +# yaml-language-server: $schema=../../../../schemas/inst_schema.json + +$schema: "inst_schema.json#" +kind: instruction +name: amomaxu.d.aq +long_name: Atomic MAX unsigned doubleword (acquire) +description: | + Atomically with acquire ordering: + + * Load the doubleword at address _xs1_ + * Write the loaded value into _xd_ + * Unsigned compare the value of register _xs2_ to the loaded value, and select the maximum value + * Write the maximum to the address in _xs1_ +definedBy: Zaamo +base: 64 +assembly: xd, xs2, (xs1) +encoding: + match: 1110010----------011-----0101111 + variables: + - name: xs2 + location: 24-20 + - name: xs1 + location: 19-15 + - name: xd + location: 11-7 +access: + s: always + u: always + vs: always + vu: always +operation(): | + if (!implemented?(ExtensionName::A) || (MISA_CSR_IMPLEMENTED && (CSR[misa].A == 1'b0))) { + raise (ExceptionCode::IllegalInstruction, mode(), $encoding); + } + + memory_model_acquire(); + + XReg virtual_address = X[xs1]; + X[xd] = amo<64>(virtual_address, X[xs2], AmoOperation::Maxu, 1'b1, 1'b0, $encoding); + +# SPDX-SnippetBegin +# SPDX-FileCopyrightText: 2017-2025 Contributors to the RISCV Sail Model +# SPDX-License-Identifier: BSD-2-Clause +sail(): | + { + if extension("A") then { + /* Get the address, X(rs1) (no offset). + * Some extensions perform additional checks on address validity. + */ + match ext_data_get_addr(rs1, zeros(), ReadWrite(Data, Data), width) { + Ext_DataAddr_Error(e) => { ext_handle_data_check_error(e); RETIRE_FAIL }, + Ext_DataAddr_OK(vaddr) => { + match translateAddr(vaddr, ReadWrite(Data, Data)) { + TR_Failure(e, _) => { handle_mem_exception(vaddr, e); RETIRE_FAIL }, + TR_Address(addr, _) => { + let eares : MemoryOpResult(unit) = match (width, sizeof(xlen)) { + (BYTE, _) => mem_write_ea(addr, 1, true & false, false, true), + (HALF, _) => mem_write_ea(addr, 2, true & false, false, true), + (WORD, _) => mem_write_ea(addr, 4, true & false, false, true), + (DOUBLE, 64) => mem_write_ea(addr, 8, true & false, false, true), + _ => internal_error(__FILE__, __LINE__, "Unexpected AMO width") + }; + let is_unsigned : bool = match op { + AMOMINU => true, + AMOMAXU => true, + _ => false + }; + let xs2_val : xlenbits = match width { + BYTE => if is_unsigned then zero_extend(X(rs2)[7..0]) else sign_extend(X(rs2)[7..0]), + HALF => if is_unsigned then zero_extend(X(rs2)[15..0]) else sign_extend(X(rs2)[15..0]), + WORD => if is_unsigned then zero_extend(X(rs2)[31..0]) else sign_extend(X(rs2)[31..0]), + DOUBLE => X(rs2) + }; + match (eares) { + MemException(e) => { handle_mem_exception(vaddr, e); RETIRE_FAIL }, + MemValue(_) => { + let mval : MemoryOpResult(xlenbits) = match (width, sizeof(xlen)) { + (BYTE, _) => extend_value(is_unsigned, mem_read(ReadWrite(Data, Data), addr, 1, true, true & false, true)), + (HALF, _) => extend_value(is_unsigned, mem_read(ReadWrite(Data, Data), addr, 2, true, true & false, true)), + (WORD, _) => extend_value(is_unsigned, mem_read(ReadWrite(Data, Data), addr, 4, true, true & false, true)), + (DOUBLE, 64) => extend_value(is_unsigned, mem_read(ReadWrite(Data, Data), addr, 8, true, true & false, true)), + _ => internal_error(__FILE__, __LINE__, "Unexpected AMO width") + }; + match (mval) { + MemException(e) => { handle_mem_exception(vaddr, e); RETIRE_FAIL }, + MemValue(loaded) => { + let result : xlenbits = + match op { + AMOSWAP => xs2_val, + AMOADD => xs2_val + loaded, + AMOXOR => xs2_val ^ loaded, + AMOAND => xs2_val & loaded, + AMOOR => xs2_val | loaded, + + /* These operations convert bitvectors to integer values using [un]signed, + * and back using to_bits(). + */ + AMOMIN => to_bits(sizeof(xlen), min(signed(xs2_val), signed(loaded))), + AMOMAX => to_bits(sizeof(xlen), max(signed(xs2_val), signed(loaded))), + AMOMINU => to_bits(sizeof(xlen), min(unsigned(xs2_val), unsigned(loaded))), + AMOMAXU => to_bits(sizeof(xlen), max(unsigned(xs2_val), unsigned(loaded))) + }; + let rval : xlenbits = match width { + BYTE => sign_extend(loaded[7..0]), + HALF => sign_extend(loaded[15..0]), + WORD => sign_extend(loaded[31..0]), + DOUBLE => loaded + }; + let wval : MemoryOpResult(bool) = match (width, sizeof(xlen)) { + (BYTE, _) => mem_write_value(addr, 1, result[7..0], true & false, false, true), + (HALF, _) => mem_write_value(addr, 2, result[15..0], true & false, false, true), + (WORD, _) => mem_write_value(addr, 4, result[31..0], true & false, false, true), + (DOUBLE, 64) => mem_write_value(addr, 8, result, true & false, false, true), + _ => internal_error(__FILE__, __LINE__, "Unexpected AMO width") + }; + match (wval) { + MemValue(true) => { X(rd) = rval; RETIRE_SUCCESS }, + MemValue(false) => { internal_error(__FILE__, __LINE__, "AMO got false from mem_write_value") }, + MemException(e) => { handle_mem_exception(vaddr, e); RETIRE_FAIL } + } + } + } + } + } + } + } + } + } + } else { + handle_illegal(); + RETIRE_FAIL + } + } + +# SPDX-SnippetEnd diff --git a/spec/std/isa/inst/Zaamo/amomaxu.d.aqrl.yaml b/spec/std/isa/inst/Zaamo/amomaxu.d.aqrl.yaml new file mode 100644 index 0000000000..3aec609b6e --- /dev/null +++ b/spec/std/isa/inst/Zaamo/amomaxu.d.aqrl.yaml @@ -0,0 +1,142 @@ +# Copyright (c) Qualcomm Technologies, Inc. and/or its subsidiaries. + +# WARNING: This file is auto-generated from spec/std/isa/inst/Zaamo/amomaxu.SIZE.AQRL.layout# Copyright (c) Abhijit Das(Sukuna0007Abhi) +# SPDX-License-Identifier: BSD-3-Clause-Clear + +# yaml-language-server: $schema=../../../../schemas/inst_schema.json + +$schema: "inst_schema.json#" +kind: instruction +name: amomaxu.d.aqrl +long_name: Atomic MAX unsigned doubleword (acquire-release) +description: | + Atomically with acquire and release ordering: + + * Load the doubleword at address _xs1_ + * Write the loaded value into _xd_ + * Unsigned compare the value of register _xs2_ to the loaded value, and select the maximum value + * Write the maximum to the address in _xs1_ +definedBy: Zaamo +base: 64 +assembly: xd, xs2, (xs1) +encoding: + match: 1110011----------011-----0101111 + variables: + - name: xs2 + location: 24-20 + - name: xs1 + location: 19-15 + - name: xd + location: 11-7 +access: + s: always + u: always + vs: always + vu: always +operation(): | + if (!implemented?(ExtensionName::A) || (MISA_CSR_IMPLEMENTED && (CSR[misa].A == 1'b0))) { + raise (ExceptionCode::IllegalInstruction, mode(), $encoding); + } + + memory_model_acquire(); + + XReg virtual_address = X[xs1]; + X[xd] = amo<64>(virtual_address, X[xs2], AmoOperation::Maxu, 1'b1, 1'b1, $encoding); + + memory_model_release(); + +# SPDX-SnippetBegin +# SPDX-FileCopyrightText: 2017-2025 Contributors to the RISCV Sail Model +# SPDX-License-Identifier: BSD-2-Clause +sail(): | + { + if extension("A") then { + /* Get the address, X(rs1) (no offset). + * Some extensions perform additional checks on address validity. + */ + match ext_data_get_addr(rs1, zeros(), ReadWrite(Data, Data), width) { + Ext_DataAddr_Error(e) => { ext_handle_data_check_error(e); RETIRE_FAIL }, + Ext_DataAddr_OK(vaddr) => { + match translateAddr(vaddr, ReadWrite(Data, Data)) { + TR_Failure(e, _) => { handle_mem_exception(vaddr, e); RETIRE_FAIL }, + TR_Address(addr, _) => { + let eares : MemoryOpResult(unit) = match (width, sizeof(xlen)) { + (BYTE, _) => mem_write_ea(addr, 1, true & true, true, true), + (HALF, _) => mem_write_ea(addr, 2, true & true, true, true), + (WORD, _) => mem_write_ea(addr, 4, true & true, true, true), + (DOUBLE, 64) => mem_write_ea(addr, 8, true & true, true, true), + _ => internal_error(__FILE__, __LINE__, "Unexpected AMO width") + }; + let is_unsigned : bool = match op { + AMOMINU => true, + AMOMAXU => true, + _ => false + }; + let xs2_val : xlenbits = match width { + BYTE => if is_unsigned then zero_extend(X(rs2)[7..0]) else sign_extend(X(rs2)[7..0]), + HALF => if is_unsigned then zero_extend(X(rs2)[15..0]) else sign_extend(X(rs2)[15..0]), + WORD => if is_unsigned then zero_extend(X(rs2)[31..0]) else sign_extend(X(rs2)[31..0]), + DOUBLE => X(rs2) + }; + match (eares) { + MemException(e) => { handle_mem_exception(vaddr, e); RETIRE_FAIL }, + MemValue(_) => { + let mval : MemoryOpResult(xlenbits) = match (width, sizeof(xlen)) { + (BYTE, _) => extend_value(is_unsigned, mem_read(ReadWrite(Data, Data), addr, 1, true, true & true, true)), + (HALF, _) => extend_value(is_unsigned, mem_read(ReadWrite(Data, Data), addr, 2, true, true & true, true)), + (WORD, _) => extend_value(is_unsigned, mem_read(ReadWrite(Data, Data), addr, 4, true, true & true, true)), + (DOUBLE, 64) => extend_value(is_unsigned, mem_read(ReadWrite(Data, Data), addr, 8, true, true & true, true)), + _ => internal_error(__FILE__, __LINE__, "Unexpected AMO width") + }; + match (mval) { + MemException(e) => { handle_mem_exception(vaddr, e); RETIRE_FAIL }, + MemValue(loaded) => { + let result : xlenbits = + match op { + AMOSWAP => xs2_val, + AMOADD => xs2_val + loaded, + AMOXOR => xs2_val ^ loaded, + AMOAND => xs2_val & loaded, + AMOOR => xs2_val | loaded, + + /* These operations convert bitvectors to integer values using [un]signed, + * and back using to_bits(). + */ + AMOMIN => to_bits(sizeof(xlen), min(signed(xs2_val), signed(loaded))), + AMOMAX => to_bits(sizeof(xlen), max(signed(xs2_val), signed(loaded))), + AMOMINU => to_bits(sizeof(xlen), min(unsigned(xs2_val), unsigned(loaded))), + AMOMAXU => to_bits(sizeof(xlen), max(unsigned(xs2_val), unsigned(loaded))) + }; + let rval : xlenbits = match width { + BYTE => sign_extend(loaded[7..0]), + HALF => sign_extend(loaded[15..0]), + WORD => sign_extend(loaded[31..0]), + DOUBLE => loaded + }; + let wval : MemoryOpResult(bool) = match (width, sizeof(xlen)) { + (BYTE, _) => mem_write_value(addr, 1, result[7..0], true & true, true, true), + (HALF, _) => mem_write_value(addr, 2, result[15..0], true & true, true, true), + (WORD, _) => mem_write_value(addr, 4, result[31..0], true & true, true, true), + (DOUBLE, 64) => mem_write_value(addr, 8, result, true & true, true, true), + _ => internal_error(__FILE__, __LINE__, "Unexpected AMO width") + }; + match (wval) { + MemValue(true) => { X(rd) = rval; RETIRE_SUCCESS }, + MemValue(false) => { internal_error(__FILE__, __LINE__, "AMO got false from mem_write_value") }, + MemException(e) => { handle_mem_exception(vaddr, e); RETIRE_FAIL } + } + } + } + } + } + } + } + } + } + } else { + handle_illegal(); + RETIRE_FAIL + } + } + +# SPDX-SnippetEnd diff --git a/spec/std/isa/inst/Zaamo/amomaxu.d.rl.yaml b/spec/std/isa/inst/Zaamo/amomaxu.d.rl.yaml new file mode 100644 index 0000000000..efac5ba631 --- /dev/null +++ b/spec/std/isa/inst/Zaamo/amomaxu.d.rl.yaml @@ -0,0 +1,140 @@ +# Copyright (c) Qualcomm Technologies, Inc. and/or its subsidiaries. + +# WARNING: This file is auto-generated from spec/std/isa/inst/Zaamo/amomaxu.SIZE.AQRL.layout# Copyright (c) Abhijit Das(Sukuna0007Abhi) +# SPDX-License-Identifier: BSD-3-Clause-Clear + +# yaml-language-server: $schema=../../../../schemas/inst_schema.json + +$schema: "inst_schema.json#" +kind: instruction +name: amomaxu.d.rl +long_name: Atomic MAX unsigned doubleword (release) +description: | + Atomically with release ordering: + + * Load the doubleword at address _xs1_ + * Write the loaded value into _xd_ + * Unsigned compare the value of register _xs2_ to the loaded value, and select the maximum value + * Write the maximum to the address in _xs1_ +definedBy: Zaamo +base: 64 +assembly: xd, xs2, (xs1) +encoding: + match: 1110001----------011-----0101111 + variables: + - name: xs2 + location: 24-20 + - name: xs1 + location: 19-15 + - name: xd + location: 11-7 +access: + s: always + u: always + vs: always + vu: always +operation(): | + if (!implemented?(ExtensionName::A) || (MISA_CSR_IMPLEMENTED && (CSR[misa].A == 1'b0))) { + raise (ExceptionCode::IllegalInstruction, mode(), $encoding); + } + + XReg virtual_address = X[xs1]; + X[xd] = amo<64>(virtual_address, X[xs2], AmoOperation::Maxu, 1'b0, 1'b1, $encoding); + + memory_model_release(); + +# SPDX-SnippetBegin +# SPDX-FileCopyrightText: 2017-2025 Contributors to the RISCV Sail Model +# SPDX-License-Identifier: BSD-2-Clause +sail(): | + { + if extension("A") then { + /* Get the address, X(rs1) (no offset). + * Some extensions perform additional checks on address validity. + */ + match ext_data_get_addr(rs1, zeros(), ReadWrite(Data, Data), width) { + Ext_DataAddr_Error(e) => { ext_handle_data_check_error(e); RETIRE_FAIL }, + Ext_DataAddr_OK(vaddr) => { + match translateAddr(vaddr, ReadWrite(Data, Data)) { + TR_Failure(e, _) => { handle_mem_exception(vaddr, e); RETIRE_FAIL }, + TR_Address(addr, _) => { + let eares : MemoryOpResult(unit) = match (width, sizeof(xlen)) { + (BYTE, _) => mem_write_ea(addr, 1, false & true, true, true), + (HALF, _) => mem_write_ea(addr, 2, false & true, true, true), + (WORD, _) => mem_write_ea(addr, 4, false & true, true, true), + (DOUBLE, 64) => mem_write_ea(addr, 8, false & true, true, true), + _ => internal_error(__FILE__, __LINE__, "Unexpected AMO width") + }; + let is_unsigned : bool = match op { + AMOMINU => true, + AMOMAXU => true, + _ => false + }; + let xs2_val : xlenbits = match width { + BYTE => if is_unsigned then zero_extend(X(rs2)[7..0]) else sign_extend(X(rs2)[7..0]), + HALF => if is_unsigned then zero_extend(X(rs2)[15..0]) else sign_extend(X(rs2)[15..0]), + WORD => if is_unsigned then zero_extend(X(rs2)[31..0]) else sign_extend(X(rs2)[31..0]), + DOUBLE => X(rs2) + }; + match (eares) { + MemException(e) => { handle_mem_exception(vaddr, e); RETIRE_FAIL }, + MemValue(_) => { + let mval : MemoryOpResult(xlenbits) = match (width, sizeof(xlen)) { + (BYTE, _) => extend_value(is_unsigned, mem_read(ReadWrite(Data, Data), addr, 1, false, false & true, true)), + (HALF, _) => extend_value(is_unsigned, mem_read(ReadWrite(Data, Data), addr, 2, false, false & true, true)), + (WORD, _) => extend_value(is_unsigned, mem_read(ReadWrite(Data, Data), addr, 4, false, false & true, true)), + (DOUBLE, 64) => extend_value(is_unsigned, mem_read(ReadWrite(Data, Data), addr, 8, false, false & true, true)), + _ => internal_error(__FILE__, __LINE__, "Unexpected AMO width") + }; + match (mval) { + MemException(e) => { handle_mem_exception(vaddr, e); RETIRE_FAIL }, + MemValue(loaded) => { + let result : xlenbits = + match op { + AMOSWAP => xs2_val, + AMOADD => xs2_val + loaded, + AMOXOR => xs2_val ^ loaded, + AMOAND => xs2_val & loaded, + AMOOR => xs2_val | loaded, + + /* These operations convert bitvectors to integer values using [un]signed, + * and back using to_bits(). + */ + AMOMIN => to_bits(sizeof(xlen), min(signed(xs2_val), signed(loaded))), + AMOMAX => to_bits(sizeof(xlen), max(signed(xs2_val), signed(loaded))), + AMOMINU => to_bits(sizeof(xlen), min(unsigned(xs2_val), unsigned(loaded))), + AMOMAXU => to_bits(sizeof(xlen), max(unsigned(xs2_val), unsigned(loaded))) + }; + let rval : xlenbits = match width { + BYTE => sign_extend(loaded[7..0]), + HALF => sign_extend(loaded[15..0]), + WORD => sign_extend(loaded[31..0]), + DOUBLE => loaded + }; + let wval : MemoryOpResult(bool) = match (width, sizeof(xlen)) { + (BYTE, _) => mem_write_value(addr, 1, result[7..0], false & true, true, true), + (HALF, _) => mem_write_value(addr, 2, result[15..0], false & true, true, true), + (WORD, _) => mem_write_value(addr, 4, result[31..0], false & true, true, true), + (DOUBLE, 64) => mem_write_value(addr, 8, result, false & true, true, true), + _ => internal_error(__FILE__, __LINE__, "Unexpected AMO width") + }; + match (wval) { + MemValue(true) => { X(rd) = rval; RETIRE_SUCCESS }, + MemValue(false) => { internal_error(__FILE__, __LINE__, "AMO got false from mem_write_value") }, + MemException(e) => { handle_mem_exception(vaddr, e); RETIRE_FAIL } + } + } + } + } + } + } + } + } + } + } else { + handle_illegal(); + RETIRE_FAIL + } + } + +# SPDX-SnippetEnd diff --git a/spec/std/isa/inst/Zaamo/amomaxu.d.yaml b/spec/std/isa/inst/Zaamo/amomaxu.d.yaml index ca04a136ae..ece42467be 100644 --- a/spec/std/isa/inst/Zaamo/amomaxu.d.yaml +++ b/spec/std/isa/inst/Zaamo/amomaxu.d.yaml @@ -1,4 +1,6 @@ # Copyright (c) Qualcomm Technologies, Inc. and/or its subsidiaries. + +# WARNING: This file is auto-generated from spec/std/isa/inst/Zaamo/amomaxu.SIZE.AQRL.layout# Copyright (c) Abhijit Das(Sukuna0007Abhi) # SPDX-License-Identifier: BSD-3-Clause-Clear # yaml-language-server: $schema=../../../../schemas/inst_schema.json @@ -18,12 +20,8 @@ definedBy: Zaamo base: 64 assembly: xd, xs2, (xs1) encoding: - match: 11100------------011-----0101111 + match: 1110000----------011-----0101111 variables: - - name: aq - location: 26 - - name: rl - location: 25 - name: xs2 location: 24-20 - name: xs1 @@ -36,14 +34,12 @@ access: vs: always vu: always operation(): | - if (implemented?(ExtensionName::A) && (CSR[misa].A == 1'b0)) { - # even though this is a memory operation, the exception occurs before that would be known, - # so mode() is the correct reporting mode rathat than effective_ldst_mode() + if (!implemented?(ExtensionName::A) || (MISA_CSR_IMPLEMENTED && (CSR[misa].A == 1'b0))) { raise (ExceptionCode::IllegalInstruction, mode(), $encoding); } - XReg virtual_address = X[xs1]; - X[xd] = amo<64>(virtual_address, X[xs2], AmoOperation::Maxu, aq, rl, $encoding); + XReg virtual_address = X[xs1]; + X[xd] = amo<64>(virtual_address, X[xs2], AmoOperation::Maxu, 1'b0, 1'b0, $encoding); # SPDX-SnippetBegin # SPDX-FileCopyrightText: 2017-2025 Contributors to the RISCV Sail Model @@ -61,10 +57,10 @@ sail(): | TR_Failure(e, _) => { handle_mem_exception(vaddr, e); RETIRE_FAIL }, TR_Address(addr, _) => { let eares : MemoryOpResult(unit) = match (width, sizeof(xlen)) { - (BYTE, _) => mem_write_ea(addr, 1, aq & rl, rl, true), - (HALF, _) => mem_write_ea(addr, 2, aq & rl, rl, true), - (WORD, _) => mem_write_ea(addr, 4, aq & rl, rl, true), - (DOUBLE, 64) => mem_write_ea(addr, 8, aq & rl, rl, true), + (BYTE, _) => mem_write_ea(addr, 1, false & false, false, true), + (HALF, _) => mem_write_ea(addr, 2, false & false, false, true), + (WORD, _) => mem_write_ea(addr, 4, false & false, false, true), + (DOUBLE, 64) => mem_write_ea(addr, 8, false & false, false, true), _ => internal_error(__FILE__, __LINE__, "Unexpected AMO width") }; let is_unsigned : bool = match op { @@ -72,7 +68,7 @@ sail(): | AMOMAXU => true, _ => false }; - let rs2_val : xlenbits = match width { + let xs2_val : xlenbits = match width { BYTE => if is_unsigned then zero_extend(X(rs2)[7..0]) else sign_extend(X(rs2)[7..0]), HALF => if is_unsigned then zero_extend(X(rs2)[15..0]) else sign_extend(X(rs2)[15..0]), WORD => if is_unsigned then zero_extend(X(rs2)[31..0]) else sign_extend(X(rs2)[31..0]), @@ -82,10 +78,10 @@ sail(): | MemException(e) => { handle_mem_exception(vaddr, e); RETIRE_FAIL }, MemValue(_) => { let mval : MemoryOpResult(xlenbits) = match (width, sizeof(xlen)) { - (BYTE, _) => extend_value(is_unsigned, mem_read(ReadWrite(Data, Data), addr, 1, aq, aq & rl, true)), - (HALF, _) => extend_value(is_unsigned, mem_read(ReadWrite(Data, Data), addr, 2, aq, aq & rl, true)), - (WORD, _) => extend_value(is_unsigned, mem_read(ReadWrite(Data, Data), addr, 4, aq, aq & rl, true)), - (DOUBLE, 64) => extend_value(is_unsigned, mem_read(ReadWrite(Data, Data), addr, 8, aq, aq & rl, true)), + (BYTE, _) => extend_value(is_unsigned, mem_read(ReadWrite(Data, Data), addr, 1, false, false & false, true)), + (HALF, _) => extend_value(is_unsigned, mem_read(ReadWrite(Data, Data), addr, 2, false, false & false, true)), + (WORD, _) => extend_value(is_unsigned, mem_read(ReadWrite(Data, Data), addr, 4, false, false & false, true)), + (DOUBLE, 64) => extend_value(is_unsigned, mem_read(ReadWrite(Data, Data), addr, 8, false, false & false, true)), _ => internal_error(__FILE__, __LINE__, "Unexpected AMO width") }; match (mval) { @@ -93,19 +89,19 @@ sail(): | MemValue(loaded) => { let result : xlenbits = match op { - AMOSWAP => rs2_val, - AMOADD => rs2_val + loaded, - AMOXOR => rs2_val ^ loaded, - AMOAND => rs2_val & loaded, - AMOOR => rs2_val | loaded, + AMOSWAP => xs2_val, + AMOADD => xs2_val + loaded, + AMOXOR => xs2_val ^ loaded, + AMOAND => xs2_val & loaded, + AMOOR => xs2_val | loaded, /* These operations convert bitvectors to integer values using [un]signed, * and back using to_bits(). */ - AMOMIN => to_bits(sizeof(xlen), min(signed(rs2_val), signed(loaded))), - AMOMAX => to_bits(sizeof(xlen), max(signed(rs2_val), signed(loaded))), - AMOMINU => to_bits(sizeof(xlen), min(unsigned(rs2_val), unsigned(loaded))), - AMOMAXU => to_bits(sizeof(xlen), max(unsigned(rs2_val), unsigned(loaded))) + AMOMIN => to_bits(sizeof(xlen), min(signed(xs2_val), signed(loaded))), + AMOMAX => to_bits(sizeof(xlen), max(signed(xs2_val), signed(loaded))), + AMOMINU => to_bits(sizeof(xlen), min(unsigned(xs2_val), unsigned(loaded))), + AMOMAXU => to_bits(sizeof(xlen), max(unsigned(xs2_val), unsigned(loaded))) }; let rval : xlenbits = match width { BYTE => sign_extend(loaded[7..0]), @@ -114,10 +110,10 @@ sail(): | DOUBLE => loaded }; let wval : MemoryOpResult(bool) = match (width, sizeof(xlen)) { - (BYTE, _) => mem_write_value(addr, 1, result[7..0], aq & rl, rl, true), - (HALF, _) => mem_write_value(addr, 2, result[15..0], aq & rl, rl, true), - (WORD, _) => mem_write_value(addr, 4, result[31..0], aq & rl, rl, true), - (DOUBLE, 64) => mem_write_value(addr, 8, result, aq & rl, rl, true), + (BYTE, _) => mem_write_value(addr, 1, result[7..0], false & false, false, true), + (HALF, _) => mem_write_value(addr, 2, result[15..0], false & false, false, true), + (WORD, _) => mem_write_value(addr, 4, result[31..0], false & false, false, true), + (DOUBLE, 64) => mem_write_value(addr, 8, result, false & false, false, true), _ => internal_error(__FILE__, __LINE__, "Unexpected AMO width") }; match (wval) { diff --git a/spec/std/isa/inst/Zaamo/amomaxu.w.aq.yaml b/spec/std/isa/inst/Zaamo/amomaxu.w.aq.yaml new file mode 100644 index 0000000000..9e43b7c59e --- /dev/null +++ b/spec/std/isa/inst/Zaamo/amomaxu.w.aq.yaml @@ -0,0 +1,139 @@ +# Copyright (c) Qualcomm Technologies, Inc. and/or its subsidiaries. + +# WARNING: This file is auto-generated from spec/std/isa/inst/Zaamo/amomaxu.SIZE.AQRL.layout# Copyright (c) Abhijit Das(Sukuna0007Abhi) +# SPDX-License-Identifier: BSD-3-Clause-Clear + +# yaml-language-server: $schema=../../../../schemas/inst_schema.json + +$schema: "inst_schema.json#" +kind: instruction +name: amomaxu.w.aq +long_name: Atomic MAX unsigned word (acquire) +description: | + Atomically with acquire ordering: + + * Load the word at address _xs1_ + * Write the sign-extended value into _xd_ + * Unsigned compare the least-significant word of register _xs2_ to the loaded value, and select the maximum value + * Write the maximum to the address in _xs1_ +definedBy: Zaamo +assembly: xd, xs2, (xs1) +encoding: + match: 1110010----------010-----0101111 + variables: + - name: xs2 + location: 24-20 + - name: xs1 + location: 19-15 + - name: xd + location: 11-7 +access: + s: always + u: always + vs: always + vu: always +operation(): | + if (!implemented?(ExtensionName::A) || (MISA_CSR_IMPLEMENTED && (CSR[misa].A == 1'b0))) { + raise (ExceptionCode::IllegalInstruction, mode(), $encoding); + } + + memory_model_acquire(); + + XReg virtual_address = X[xs1]; + X[xd] = amo<32>(virtual_address, X[xs2][31:0], AmoOperation::Maxu, 1'b1, 1'b0, $encoding); + +# SPDX-SnippetBegin +# SPDX-FileCopyrightText: 2017-2025 Contributors to the RISCV Sail Model +# SPDX-License-Identifier: BSD-2-Clause +sail(): | + { + if extension("A") then { + /* Get the address, X(rs1) (no offset). + * Some extensions perform additional checks on address validity. + */ + match ext_data_get_addr(rs1, zeros(), ReadWrite(Data, Data), width) { + Ext_DataAddr_Error(e) => { ext_handle_data_check_error(e); RETIRE_FAIL }, + Ext_DataAddr_OK(vaddr) => { + match translateAddr(vaddr, ReadWrite(Data, Data)) { + TR_Failure(e, _) => { handle_mem_exception(vaddr, e); RETIRE_FAIL }, + TR_Address(addr, _) => { + let eares : MemoryOpResult(unit) = match (width, sizeof(xlen)) { + (BYTE, _) => mem_write_ea(addr, 1, true & false, false, true), + (HALF, _) => mem_write_ea(addr, 2, true & false, false, true), + (WORD, _) => mem_write_ea(addr, 4, true & false, false, true), + (DOUBLE, 64) => mem_write_ea(addr, 8, true & false, false, true), + _ => internal_error(__FILE__, __LINE__, "Unexpected AMO width") + }; + let is_unsigned : bool = match op { + AMOMINU => true, + AMOMAXU => true, + _ => false + }; + let xs2_val : xlenbits = match width { + BYTE => if is_unsigned then zero_extend(X(rs2)[7..0]) else sign_extend(X(rs2)[7..0]), + HALF => if is_unsigned then zero_extend(X(rs2)[15..0]) else sign_extend(X(rs2)[15..0]), + WORD => if is_unsigned then zero_extend(X(rs2)[31..0]) else sign_extend(X(rs2)[31..0]), + DOUBLE => X(rs2) + }; + match (eares) { + MemException(e) => { handle_mem_exception(vaddr, e); RETIRE_FAIL }, + MemValue(_) => { + let mval : MemoryOpResult(xlenbits) = match (width, sizeof(xlen)) { + (BYTE, _) => extend_value(is_unsigned, mem_read(ReadWrite(Data, Data), addr, 1, true, true & false, true)), + (HALF, _) => extend_value(is_unsigned, mem_read(ReadWrite(Data, Data), addr, 2, true, true & false, true)), + (WORD, _) => extend_value(is_unsigned, mem_read(ReadWrite(Data, Data), addr, 4, true, true & false, true)), + (DOUBLE, 64) => extend_value(is_unsigned, mem_read(ReadWrite(Data, Data), addr, 8, true, true & false, true)), + _ => internal_error(__FILE__, __LINE__, "Unexpected AMO width") + }; + match (mval) { + MemException(e) => { handle_mem_exception(vaddr, e); RETIRE_FAIL }, + MemValue(loaded) => { + let result : xlenbits = + match op { + AMOSWAP => xs2_val, + AMOADD => xs2_val + loaded, + AMOXOR => xs2_val ^ loaded, + AMOAND => xs2_val & loaded, + AMOOR => xs2_val | loaded, + + /* These operations convert bitvectors to integer values using [un]signed, + * and back using to_bits(). + */ + AMOMIN => to_bits(sizeof(xlen), min(signed(xs2_val), signed(loaded))), + AMOMAX => to_bits(sizeof(xlen), max(signed(xs2_val), signed(loaded))), + AMOMINU => to_bits(sizeof(xlen), min(unsigned(xs2_val), unsigned(loaded))), + AMOMAXU => to_bits(sizeof(xlen), max(unsigned(xs2_val), unsigned(loaded))) + }; + let rval : xlenbits = match width { + BYTE => sign_extend(loaded[7..0]), + HALF => sign_extend(loaded[15..0]), + WORD => sign_extend(loaded[31..0]), + DOUBLE => loaded + }; + let wval : MemoryOpResult(bool) = match (width, sizeof(xlen)) { + (BYTE, _) => mem_write_value(addr, 1, result[7..0], true & false, false, true), + (HALF, _) => mem_write_value(addr, 2, result[15..0], true & false, false, true), + (WORD, _) => mem_write_value(addr, 4, result[31..0], true & false, false, true), + (DOUBLE, 64) => mem_write_value(addr, 8, result, true & false, false, true), + _ => internal_error(__FILE__, __LINE__, "Unexpected AMO width") + }; + match (wval) { + MemValue(true) => { X(rd) = rval; RETIRE_SUCCESS }, + MemValue(false) => { internal_error(__FILE__, __LINE__, "AMO got false from mem_write_value") }, + MemException(e) => { handle_mem_exception(vaddr, e); RETIRE_FAIL } + } + } + } + } + } + } + } + } + } + } else { + handle_illegal(); + RETIRE_FAIL + } + } + +# SPDX-SnippetEnd diff --git a/spec/std/isa/inst/Zaamo/amomaxu.w.aqrl.yaml b/spec/std/isa/inst/Zaamo/amomaxu.w.aqrl.yaml new file mode 100644 index 0000000000..809e6f1d82 --- /dev/null +++ b/spec/std/isa/inst/Zaamo/amomaxu.w.aqrl.yaml @@ -0,0 +1,141 @@ +# Copyright (c) Qualcomm Technologies, Inc. and/or its subsidiaries. + +# WARNING: This file is auto-generated from spec/std/isa/inst/Zaamo/amomaxu.SIZE.AQRL.layout# Copyright (c) Abhijit Das(Sukuna0007Abhi) +# SPDX-License-Identifier: BSD-3-Clause-Clear + +# yaml-language-server: $schema=../../../../schemas/inst_schema.json + +$schema: "inst_schema.json#" +kind: instruction +name: amomaxu.w.aqrl +long_name: Atomic MAX unsigned word (acquire-release) +description: | + Atomically with acquire and release ordering: + + * Load the word at address _xs1_ + * Write the sign-extended value into _xd_ + * Unsigned compare the least-significant word of register _xs2_ to the loaded value, and select the maximum value + * Write the maximum to the address in _xs1_ +definedBy: Zaamo +assembly: xd, xs2, (xs1) +encoding: + match: 1110011----------010-----0101111 + variables: + - name: xs2 + location: 24-20 + - name: xs1 + location: 19-15 + - name: xd + location: 11-7 +access: + s: always + u: always + vs: always + vu: always +operation(): | + if (!implemented?(ExtensionName::A) || (MISA_CSR_IMPLEMENTED && (CSR[misa].A == 1'b0))) { + raise (ExceptionCode::IllegalInstruction, mode(), $encoding); + } + + memory_model_acquire(); + + XReg virtual_address = X[xs1]; + X[xd] = amo<32>(virtual_address, X[xs2][31:0], AmoOperation::Maxu, 1'b1, 1'b1, $encoding); + + memory_model_release(); + +# SPDX-SnippetBegin +# SPDX-FileCopyrightText: 2017-2025 Contributors to the RISCV Sail Model +# SPDX-License-Identifier: BSD-2-Clause +sail(): | + { + if extension("A") then { + /* Get the address, X(rs1) (no offset). + * Some extensions perform additional checks on address validity. + */ + match ext_data_get_addr(rs1, zeros(), ReadWrite(Data, Data), width) { + Ext_DataAddr_Error(e) => { ext_handle_data_check_error(e); RETIRE_FAIL }, + Ext_DataAddr_OK(vaddr) => { + match translateAddr(vaddr, ReadWrite(Data, Data)) { + TR_Failure(e, _) => { handle_mem_exception(vaddr, e); RETIRE_FAIL }, + TR_Address(addr, _) => { + let eares : MemoryOpResult(unit) = match (width, sizeof(xlen)) { + (BYTE, _) => mem_write_ea(addr, 1, true & true, true, true), + (HALF, _) => mem_write_ea(addr, 2, true & true, true, true), + (WORD, _) => mem_write_ea(addr, 4, true & true, true, true), + (DOUBLE, 64) => mem_write_ea(addr, 8, true & true, true, true), + _ => internal_error(__FILE__, __LINE__, "Unexpected AMO width") + }; + let is_unsigned : bool = match op { + AMOMINU => true, + AMOMAXU => true, + _ => false + }; + let xs2_val : xlenbits = match width { + BYTE => if is_unsigned then zero_extend(X(rs2)[7..0]) else sign_extend(X(rs2)[7..0]), + HALF => if is_unsigned then zero_extend(X(rs2)[15..0]) else sign_extend(X(rs2)[15..0]), + WORD => if is_unsigned then zero_extend(X(rs2)[31..0]) else sign_extend(X(rs2)[31..0]), + DOUBLE => X(rs2) + }; + match (eares) { + MemException(e) => { handle_mem_exception(vaddr, e); RETIRE_FAIL }, + MemValue(_) => { + let mval : MemoryOpResult(xlenbits) = match (width, sizeof(xlen)) { + (BYTE, _) => extend_value(is_unsigned, mem_read(ReadWrite(Data, Data), addr, 1, true, true & true, true)), + (HALF, _) => extend_value(is_unsigned, mem_read(ReadWrite(Data, Data), addr, 2, true, true & true, true)), + (WORD, _) => extend_value(is_unsigned, mem_read(ReadWrite(Data, Data), addr, 4, true, true & true, true)), + (DOUBLE, 64) => extend_value(is_unsigned, mem_read(ReadWrite(Data, Data), addr, 8, true, true & true, true)), + _ => internal_error(__FILE__, __LINE__, "Unexpected AMO width") + }; + match (mval) { + MemException(e) => { handle_mem_exception(vaddr, e); RETIRE_FAIL }, + MemValue(loaded) => { + let result : xlenbits = + match op { + AMOSWAP => xs2_val, + AMOADD => xs2_val + loaded, + AMOXOR => xs2_val ^ loaded, + AMOAND => xs2_val & loaded, + AMOOR => xs2_val | loaded, + + /* These operations convert bitvectors to integer values using [un]signed, + * and back using to_bits(). + */ + AMOMIN => to_bits(sizeof(xlen), min(signed(xs2_val), signed(loaded))), + AMOMAX => to_bits(sizeof(xlen), max(signed(xs2_val), signed(loaded))), + AMOMINU => to_bits(sizeof(xlen), min(unsigned(xs2_val), unsigned(loaded))), + AMOMAXU => to_bits(sizeof(xlen), max(unsigned(xs2_val), unsigned(loaded))) + }; + let rval : xlenbits = match width { + BYTE => sign_extend(loaded[7..0]), + HALF => sign_extend(loaded[15..0]), + WORD => sign_extend(loaded[31..0]), + DOUBLE => loaded + }; + let wval : MemoryOpResult(bool) = match (width, sizeof(xlen)) { + (BYTE, _) => mem_write_value(addr, 1, result[7..0], true & true, true, true), + (HALF, _) => mem_write_value(addr, 2, result[15..0], true & true, true, true), + (WORD, _) => mem_write_value(addr, 4, result[31..0], true & true, true, true), + (DOUBLE, 64) => mem_write_value(addr, 8, result, true & true, true, true), + _ => internal_error(__FILE__, __LINE__, "Unexpected AMO width") + }; + match (wval) { + MemValue(true) => { X(rd) = rval; RETIRE_SUCCESS }, + MemValue(false) => { internal_error(__FILE__, __LINE__, "AMO got false from mem_write_value") }, + MemException(e) => { handle_mem_exception(vaddr, e); RETIRE_FAIL } + } + } + } + } + } + } + } + } + } + } else { + handle_illegal(); + RETIRE_FAIL + } + } + +# SPDX-SnippetEnd diff --git a/spec/std/isa/inst/Zaamo/amomaxu.w.rl.yaml b/spec/std/isa/inst/Zaamo/amomaxu.w.rl.yaml new file mode 100644 index 0000000000..3129dd52e6 --- /dev/null +++ b/spec/std/isa/inst/Zaamo/amomaxu.w.rl.yaml @@ -0,0 +1,139 @@ +# Copyright (c) Qualcomm Technologies, Inc. and/or its subsidiaries. + +# WARNING: This file is auto-generated from spec/std/isa/inst/Zaamo/amomaxu.SIZE.AQRL.layout# Copyright (c) Abhijit Das(Sukuna0007Abhi) +# SPDX-License-Identifier: BSD-3-Clause-Clear + +# yaml-language-server: $schema=../../../../schemas/inst_schema.json + +$schema: "inst_schema.json#" +kind: instruction +name: amomaxu.w.rl +long_name: Atomic MAX unsigned word (release) +description: | + Atomically with release ordering: + + * Load the word at address _xs1_ + * Write the sign-extended value into _xd_ + * Unsigned compare the least-significant word of register _xs2_ to the loaded value, and select the maximum value + * Write the maximum to the address in _xs1_ +definedBy: Zaamo +assembly: xd, xs2, (xs1) +encoding: + match: 1110001----------010-----0101111 + variables: + - name: xs2 + location: 24-20 + - name: xs1 + location: 19-15 + - name: xd + location: 11-7 +access: + s: always + u: always + vs: always + vu: always +operation(): | + if (!implemented?(ExtensionName::A) || (MISA_CSR_IMPLEMENTED && (CSR[misa].A == 1'b0))) { + raise (ExceptionCode::IllegalInstruction, mode(), $encoding); + } + + XReg virtual_address = X[xs1]; + X[xd] = amo<32>(virtual_address, X[xs2][31:0], AmoOperation::Maxu, 1'b0, 1'b1, $encoding); + + memory_model_release(); + +# SPDX-SnippetBegin +# SPDX-FileCopyrightText: 2017-2025 Contributors to the RISCV Sail Model +# SPDX-License-Identifier: BSD-2-Clause +sail(): | + { + if extension("A") then { + /* Get the address, X(rs1) (no offset). + * Some extensions perform additional checks on address validity. + */ + match ext_data_get_addr(rs1, zeros(), ReadWrite(Data, Data), width) { + Ext_DataAddr_Error(e) => { ext_handle_data_check_error(e); RETIRE_FAIL }, + Ext_DataAddr_OK(vaddr) => { + match translateAddr(vaddr, ReadWrite(Data, Data)) { + TR_Failure(e, _) => { handle_mem_exception(vaddr, e); RETIRE_FAIL }, + TR_Address(addr, _) => { + let eares : MemoryOpResult(unit) = match (width, sizeof(xlen)) { + (BYTE, _) => mem_write_ea(addr, 1, false & true, true, true), + (HALF, _) => mem_write_ea(addr, 2, false & true, true, true), + (WORD, _) => mem_write_ea(addr, 4, false & true, true, true), + (DOUBLE, 64) => mem_write_ea(addr, 8, false & true, true, true), + _ => internal_error(__FILE__, __LINE__, "Unexpected AMO width") + }; + let is_unsigned : bool = match op { + AMOMINU => true, + AMOMAXU => true, + _ => false + }; + let xs2_val : xlenbits = match width { + BYTE => if is_unsigned then zero_extend(X(rs2)[7..0]) else sign_extend(X(rs2)[7..0]), + HALF => if is_unsigned then zero_extend(X(rs2)[15..0]) else sign_extend(X(rs2)[15..0]), + WORD => if is_unsigned then zero_extend(X(rs2)[31..0]) else sign_extend(X(rs2)[31..0]), + DOUBLE => X(rs2) + }; + match (eares) { + MemException(e) => { handle_mem_exception(vaddr, e); RETIRE_FAIL }, + MemValue(_) => { + let mval : MemoryOpResult(xlenbits) = match (width, sizeof(xlen)) { + (BYTE, _) => extend_value(is_unsigned, mem_read(ReadWrite(Data, Data), addr, 1, false, false & true, true)), + (HALF, _) => extend_value(is_unsigned, mem_read(ReadWrite(Data, Data), addr, 2, false, false & true, true)), + (WORD, _) => extend_value(is_unsigned, mem_read(ReadWrite(Data, Data), addr, 4, false, false & true, true)), + (DOUBLE, 64) => extend_value(is_unsigned, mem_read(ReadWrite(Data, Data), addr, 8, false, false & true, true)), + _ => internal_error(__FILE__, __LINE__, "Unexpected AMO width") + }; + match (mval) { + MemException(e) => { handle_mem_exception(vaddr, e); RETIRE_FAIL }, + MemValue(loaded) => { + let result : xlenbits = + match op { + AMOSWAP => xs2_val, + AMOADD => xs2_val + loaded, + AMOXOR => xs2_val ^ loaded, + AMOAND => xs2_val & loaded, + AMOOR => xs2_val | loaded, + + /* These operations convert bitvectors to integer values using [un]signed, + * and back using to_bits(). + */ + AMOMIN => to_bits(sizeof(xlen), min(signed(xs2_val), signed(loaded))), + AMOMAX => to_bits(sizeof(xlen), max(signed(xs2_val), signed(loaded))), + AMOMINU => to_bits(sizeof(xlen), min(unsigned(xs2_val), unsigned(loaded))), + AMOMAXU => to_bits(sizeof(xlen), max(unsigned(xs2_val), unsigned(loaded))) + }; + let rval : xlenbits = match width { + BYTE => sign_extend(loaded[7..0]), + HALF => sign_extend(loaded[15..0]), + WORD => sign_extend(loaded[31..0]), + DOUBLE => loaded + }; + let wval : MemoryOpResult(bool) = match (width, sizeof(xlen)) { + (BYTE, _) => mem_write_value(addr, 1, result[7..0], false & true, true, true), + (HALF, _) => mem_write_value(addr, 2, result[15..0], false & true, true, true), + (WORD, _) => mem_write_value(addr, 4, result[31..0], false & true, true, true), + (DOUBLE, 64) => mem_write_value(addr, 8, result, false & true, true, true), + _ => internal_error(__FILE__, __LINE__, "Unexpected AMO width") + }; + match (wval) { + MemValue(true) => { X(rd) = rval; RETIRE_SUCCESS }, + MemValue(false) => { internal_error(__FILE__, __LINE__, "AMO got false from mem_write_value") }, + MemException(e) => { handle_mem_exception(vaddr, e); RETIRE_FAIL } + } + } + } + } + } + } + } + } + } + } else { + handle_illegal(); + RETIRE_FAIL + } + } + +# SPDX-SnippetEnd diff --git a/spec/std/isa/inst/Zaamo/amomaxu.w.yaml b/spec/std/isa/inst/Zaamo/amomaxu.w.yaml index 3ecb2bf333..37fa6f7a21 100644 --- a/spec/std/isa/inst/Zaamo/amomaxu.w.yaml +++ b/spec/std/isa/inst/Zaamo/amomaxu.w.yaml @@ -1,4 +1,6 @@ # Copyright (c) Qualcomm Technologies, Inc. and/or its subsidiaries. + +# WARNING: This file is auto-generated from spec/std/isa/inst/Zaamo/amomaxu.SIZE.AQRL.layout# Copyright (c) Abhijit Das(Sukuna0007Abhi) # SPDX-License-Identifier: BSD-3-Clause-Clear # yaml-language-server: $schema=../../../../schemas/inst_schema.json @@ -17,12 +19,8 @@ description: | definedBy: Zaamo assembly: xd, xs2, (xs1) encoding: - match: 11100------------010-----0101111 + match: 1110000----------010-----0101111 variables: - - name: aq - location: 26 - - name: rl - location: 25 - name: xs2 location: 24-20 - name: xs1 @@ -35,15 +33,12 @@ access: vs: always vu: always operation(): | - if (implemented?(ExtensionName::A) && (CSR[misa].A == 1'b0)) { - # even though this is a memory operation, the exception occurs before that would be known, - # so mode() is the correct reporting mode rathat than effective_ldst_mode() + if (!implemented?(ExtensionName::A) || (MISA_CSR_IMPLEMENTED && (CSR[misa].A == 1'b0))) { raise (ExceptionCode::IllegalInstruction, mode(), $encoding); } XReg virtual_address = X[xs1]; - - X[xd] = amo<32>(virtual_address, X[xs2][31:0], AmoOperation::Maxu, aq, rl, $encoding); + X[xd] = amo<32>(virtual_address, X[xs2][31:0], AmoOperation::Maxu, 1'b0, 1'b0, $encoding); # SPDX-SnippetBegin # SPDX-FileCopyrightText: 2017-2025 Contributors to the RISCV Sail Model @@ -61,10 +56,10 @@ sail(): | TR_Failure(e, _) => { handle_mem_exception(vaddr, e); RETIRE_FAIL }, TR_Address(addr, _) => { let eares : MemoryOpResult(unit) = match (width, sizeof(xlen)) { - (BYTE, _) => mem_write_ea(addr, 1, aq & rl, rl, true), - (HALF, _) => mem_write_ea(addr, 2, aq & rl, rl, true), - (WORD, _) => mem_write_ea(addr, 4, aq & rl, rl, true), - (DOUBLE, 64) => mem_write_ea(addr, 8, aq & rl, rl, true), + (BYTE, _) => mem_write_ea(addr, 1, false & false, false, true), + (HALF, _) => mem_write_ea(addr, 2, false & false, false, true), + (WORD, _) => mem_write_ea(addr, 4, false & false, false, true), + (DOUBLE, 64) => mem_write_ea(addr, 8, false & false, false, true), _ => internal_error(__FILE__, __LINE__, "Unexpected AMO width") }; let is_unsigned : bool = match op { @@ -72,7 +67,7 @@ sail(): | AMOMAXU => true, _ => false }; - let rs2_val : xlenbits = match width { + let xs2_val : xlenbits = match width { BYTE => if is_unsigned then zero_extend(X(rs2)[7..0]) else sign_extend(X(rs2)[7..0]), HALF => if is_unsigned then zero_extend(X(rs2)[15..0]) else sign_extend(X(rs2)[15..0]), WORD => if is_unsigned then zero_extend(X(rs2)[31..0]) else sign_extend(X(rs2)[31..0]), @@ -82,10 +77,10 @@ sail(): | MemException(e) => { handle_mem_exception(vaddr, e); RETIRE_FAIL }, MemValue(_) => { let mval : MemoryOpResult(xlenbits) = match (width, sizeof(xlen)) { - (BYTE, _) => extend_value(is_unsigned, mem_read(ReadWrite(Data, Data), addr, 1, aq, aq & rl, true)), - (HALF, _) => extend_value(is_unsigned, mem_read(ReadWrite(Data, Data), addr, 2, aq, aq & rl, true)), - (WORD, _) => extend_value(is_unsigned, mem_read(ReadWrite(Data, Data), addr, 4, aq, aq & rl, true)), - (DOUBLE, 64) => extend_value(is_unsigned, mem_read(ReadWrite(Data, Data), addr, 8, aq, aq & rl, true)), + (BYTE, _) => extend_value(is_unsigned, mem_read(ReadWrite(Data, Data), addr, 1, false, false & false, true)), + (HALF, _) => extend_value(is_unsigned, mem_read(ReadWrite(Data, Data), addr, 2, false, false & false, true)), + (WORD, _) => extend_value(is_unsigned, mem_read(ReadWrite(Data, Data), addr, 4, false, false & false, true)), + (DOUBLE, 64) => extend_value(is_unsigned, mem_read(ReadWrite(Data, Data), addr, 8, false, false & false, true)), _ => internal_error(__FILE__, __LINE__, "Unexpected AMO width") }; match (mval) { @@ -93,19 +88,19 @@ sail(): | MemValue(loaded) => { let result : xlenbits = match op { - AMOSWAP => rs2_val, - AMOADD => rs2_val + loaded, - AMOXOR => rs2_val ^ loaded, - AMOAND => rs2_val & loaded, - AMOOR => rs2_val | loaded, + AMOSWAP => xs2_val, + AMOADD => xs2_val + loaded, + AMOXOR => xs2_val ^ loaded, + AMOAND => xs2_val & loaded, + AMOOR => xs2_val | loaded, /* These operations convert bitvectors to integer values using [un]signed, * and back using to_bits(). */ - AMOMIN => to_bits(sizeof(xlen), min(signed(rs2_val), signed(loaded))), - AMOMAX => to_bits(sizeof(xlen), max(signed(rs2_val), signed(loaded))), - AMOMINU => to_bits(sizeof(xlen), min(unsigned(rs2_val), unsigned(loaded))), - AMOMAXU => to_bits(sizeof(xlen), max(unsigned(rs2_val), unsigned(loaded))) + AMOMIN => to_bits(sizeof(xlen), min(signed(xs2_val), signed(loaded))), + AMOMAX => to_bits(sizeof(xlen), max(signed(xs2_val), signed(loaded))), + AMOMINU => to_bits(sizeof(xlen), min(unsigned(xs2_val), unsigned(loaded))), + AMOMAXU => to_bits(sizeof(xlen), max(unsigned(xs2_val), unsigned(loaded))) }; let rval : xlenbits = match width { BYTE => sign_extend(loaded[7..0]), @@ -114,10 +109,10 @@ sail(): | DOUBLE => loaded }; let wval : MemoryOpResult(bool) = match (width, sizeof(xlen)) { - (BYTE, _) => mem_write_value(addr, 1, result[7..0], aq & rl, rl, true), - (HALF, _) => mem_write_value(addr, 2, result[15..0], aq & rl, rl, true), - (WORD, _) => mem_write_value(addr, 4, result[31..0], aq & rl, rl, true), - (DOUBLE, 64) => mem_write_value(addr, 8, result, aq & rl, rl, true), + (BYTE, _) => mem_write_value(addr, 1, result[7..0], false & false, false, true), + (HALF, _) => mem_write_value(addr, 2, result[15..0], false & false, false, true), + (WORD, _) => mem_write_value(addr, 4, result[31..0], false & false, false, true), + (DOUBLE, 64) => mem_write_value(addr, 8, result, false & false, false, true), _ => internal_error(__FILE__, __LINE__, "Unexpected AMO width") }; match (wval) { diff --git a/spec/std/isa/inst/Zaamo/amomin.SIZE.AQRL.layout b/spec/std/isa/inst/Zaamo/amomin.SIZE.AQRL.layout new file mode 100644 index 0000000000..9a768c7cfc --- /dev/null +++ b/spec/std/isa/inst/Zaamo/amomin.SIZE.AQRL.layout @@ -0,0 +1,175 @@ +# Copyright (c) Qualcomm Technologies, Inc. and/or its subsidiaries. +# Copyright (c) Abhijit Das(Sukuna0007Abhi) +# SPDX-License-Identifier: BSD-3-Clause-Clear + +# yaml-language-server: $schema=../../../../schemas/inst_schema.json +<%- + raise "'size' must be defined as 'b', 'h', 'w', or 'd'" unless %w[b h w d].include?(size) + raise "'aq' must be defined as true or false" unless [true, false].include?(aq) + raise "'rl' must be defined as true or false" unless [true, false].include?(rl) + + size_info = { + "b" => { name: "byte", bits: 8, funct3: "000", operation_bits: "8" }, + "h" => { name: "halfword", bits: 16, funct3: "001", operation_bits: "16" }, + "w" => { name: "word", bits: 32, funct3: "010", operation_bits: "32" }, + "d" => { name: "doubleword", bits: 64, funct3: "011", operation_bits: "64" } + } + + current_size = size_info[size] + + # Generate instruction name suffix based on aq/rl + aq_rl_suffix = "" + if aq && rl + aq_rl_suffix = ".aqrl" + elsif aq + aq_rl_suffix = ".aq" + elsif rl + aq_rl_suffix = ".rl" + end + + # Generate match string with fixed aq/rl bits + aq_bit = aq ? "1" : "0" + rl_bit = rl ? "1" : "0" +-%> + +$schema: "inst_schema.json#" +kind: instruction +name: amomin.<%= size %><%= aq_rl_suffix %> +long_name: Atomic MIN <%= current_size[:name] %><%= aq && rl ? " (acquire-release)" : (aq ? " (acquire)" : (rl ? " (release)" : "")) %> +description: | + Atomically<%= aq && rl ? " with acquire and release ordering" : (aq ? " with acquire ordering" : (rl ? " with release ordering" : "")) %>: + + * Load the <%= current_size[:name] %> at address _xs1_ + * Write the <%= %w[b h w].include?(size) ? "sign-extended value" : "loaded value" %> into _xd_ + * Signed compare the <%= %w[b h w].include?(size) ? "least-significant #{current_size[:name]} of register" : "value of register" %> _xs2_ to the loaded value, and select the minimum value + * Write the minimum to the address in _xs1_ +definedBy: <%= %w[b h].include?(size) ? "Zabha" : "Zaamo" %> +<%- if size == "d" -%> +base: 64 +<%- end -%> +assembly: xd, xs2, (xs1) +encoding: + match: 10000<%= aq_bit %><%= rl_bit %>----------<%= current_size[:funct3] %>-----0101111 + variables: + - name: xs2 + location: 24-20 + - name: xs1 + location: 19-15 + - name: xd + location: 11-7 +access: + s: always + u: always + vs: always + vu: always +operation(): | + if (!implemented?(ExtensionName::A) || (MISA_CSR_IMPLEMENTED && (CSR[misa].A == 1'b0))) { + raise (ExceptionCode::IllegalInstruction, mode(), $encoding); + } + +<% if aq -%> + memory_model_acquire(); + +<% end -%> + XReg virtual_address = X[xs1]; + X[xd] = amo<<%= current_size[:operation_bits] %>>(virtual_address, X[xs2]<%= %w[b h w].include?(size) ? "[#{current_size[:bits]-1}:0]" : "" %>, AmoOperation::Min, <%= aq ? "1'b1" : "1'b0" %>, <%= rl ? "1'b1" : "1'b0" %>, $encoding); +<% if rl -%> + + memory_model_release(); +<% end -%> + +# SPDX-SnippetBegin +# SPDX-FileCopyrightText: 2017-2025 Contributors to the RISCV Sail Model +# SPDX-License-Identifier: BSD-2-Clause +sail(): | + { + if extension("A") then { + /* Get the address, X(rs1) (no offset). + * Some extensions perform additional checks on address validity. + */ + match ext_data_get_addr(rs1, zeros(), ReadWrite(Data, Data), width) { + Ext_DataAddr_Error(e) => { ext_handle_data_check_error(e); RETIRE_FAIL }, + Ext_DataAddr_OK(vaddr) => { + match translateAddr(vaddr, ReadWrite(Data, Data)) { + TR_Failure(e, _) => { handle_mem_exception(vaddr, e); RETIRE_FAIL }, + TR_Address(addr, _) => { + let eares : MemoryOpResult(unit) = match (width, sizeof(xlen)) { + (BYTE, _) => mem_write_ea(addr, 1, aq & rl, rl, true), + (HALF, _) => mem_write_ea(addr, 2, aq & rl, rl, true), + (WORD, _) => mem_write_ea(addr, 4, aq & rl, rl, true), + (DOUBLE, 64) => mem_write_ea(addr, 8, aq & rl, rl, true), + _ => internal_error(__FILE__, __LINE__, "Unexpected AMO width") + }; + let is_unsigned : bool = match op { + AMOMINU => true, + AMOMAXU => true, + _ => false + }; + let rs2_val : xlenbits = match width { + BYTE => if is_unsigned then zero_extend(X(rs2)[7..0]) else sign_extend(X(rs2)[7..0]), + HALF => if is_unsigned then zero_extend(X(rs2)[15..0]) else sign_extend(X(rs2)[15..0]), + WORD => if is_unsigned then zero_extend(X(rs2)[31..0]) else sign_extend(X(rs2)[31..0]), + DOUBLE => X(rs2) + }; + match (eares) { + MemException(e) => { handle_mem_exception(vaddr, e); RETIRE_FAIL }, + MemValue(_) => { + let mval : MemoryOpResult(xlenbits) = match (width, sizeof(xlen)) { + (BYTE, _) => extend_value(is_unsigned, mem_read(ReadWrite(Data, Data), addr, 1, aq, aq & rl, true)), + (HALF, _) => extend_value(is_unsigned, mem_read(ReadWrite(Data, Data), addr, 2, aq, aq & rl, true)), + (WORD, _) => extend_value(is_unsigned, mem_read(ReadWrite(Data, Data), addr, 4, aq, aq & rl, true)), + (DOUBLE, 64) => extend_value(is_unsigned, mem_read(ReadWrite(Data, Data), addr, 8, aq, aq & rl, true)), + _ => internal_error(__FILE__, __LINE__, "Unexpected AMO width") + }; + match (mval) { + MemException(e) => { handle_mem_exception(vaddr, e); RETIRE_FAIL }, + MemValue(loaded) => { + let result : xlenbits = + match op { + AMOSWAP => rs2_val, + AMOADD => rs2_val + loaded, + AMOXOR => rs2_val ^ loaded, + AMOAND => rs2_val & loaded, + AMOOR => rs2_val | loaded, + + /* These operations convert bitvectors to integer values using [un]signed, + * and back using to_bits(). + */ + AMOMIN => to_bits(sizeof(xlen), min(signed(rs2_val), signed(loaded))), + AMOMAX => to_bits(sizeof(xlen), max(signed(rs2_val), signed(loaded))), + AMOMINU => to_bits(sizeof(xlen), min(unsigned(rs2_val), unsigned(loaded))), + AMOMAXU => to_bits(sizeof(xlen), max(unsigned(rs2_val), unsigned(loaded))) + }; + let rval : xlenbits = match width { + BYTE => sign_extend(loaded[7..0]), + HALF => sign_extend(loaded[15..0]), + WORD => sign_extend(loaded[31..0]), + DOUBLE => loaded + }; + let wval : MemoryOpResult(bool) = match (width, sizeof(xlen)) { + (BYTE, _) => mem_write_value(addr, 1, result[7..0], aq & rl, rl, true), + (HALF, _) => mem_write_value(addr, 2, result[15..0], aq & rl, rl, true), + (WORD, _) => mem_write_value(addr, 4, result[31..0], aq & rl, rl, true), + (DOUBLE, 64) => mem_write_value(addr, 8, result, aq & rl, rl, true), + _ => internal_error(__FILE__, __LINE__, "Unexpected AMO width") + }; + match (wval) { + MemValue(true) => { X(rd) = rval; RETIRE_SUCCESS }, + MemValue(false) => { internal_error(__FILE__, __LINE__, "AMO got false from mem_write_value") }, + MemException(e) => { handle_mem_exception(vaddr, e); RETIRE_FAIL } + } + } + } + } + } + } + } + } + } + } else { + handle_illegal(); + RETIRE_FAIL + } + } + +# SPDX-SnippetEnd diff --git a/spec/std/isa/inst/Zaamo/amomin.d.aq.yaml b/spec/std/isa/inst/Zaamo/amomin.d.aq.yaml new file mode 100644 index 0000000000..62d1e0fdc7 --- /dev/null +++ b/spec/std/isa/inst/Zaamo/amomin.d.aq.yaml @@ -0,0 +1,140 @@ +# Copyright (c) Qualcomm Technologies, Inc. and/or its subsidiaries. + +# WARNING: This file is auto-generated from spec/std/isa/inst/Zaamo/amomin.SIZE.AQRL.layout# Copyright (c) Abhijit Das(Sukuna0007Abhi) +# SPDX-License-Identifier: BSD-3-Clause-Clear + +# yaml-language-server: $schema=../../../../schemas/inst_schema.json + +$schema: "inst_schema.json#" +kind: instruction +name: amomin.d.aq +long_name: Atomic MIN doubleword (acquire) +description: | + Atomically with acquire ordering: + + * Load the doubleword at address _xs1_ + * Write the loaded value into _xd_ + * Signed compare the value of register _xs2_ to the loaded value, and select the minimum value + * Write the minimum to the address in _xs1_ +definedBy: Zaamo +base: 64 +assembly: xd, xs2, (xs1) +encoding: + match: 1000010----------011-----0101111 + variables: + - name: xs2 + location: 24-20 + - name: xs1 + location: 19-15 + - name: xd + location: 11-7 +access: + s: always + u: always + vs: always + vu: always +operation(): | + if (!implemented?(ExtensionName::A) || (MISA_CSR_IMPLEMENTED && (CSR[misa].A == 1'b0))) { + raise (ExceptionCode::IllegalInstruction, mode(), $encoding); + } + + memory_model_acquire(); + + XReg virtual_address = X[xs1]; + X[xd] = amo<64>(virtual_address, X[xs2], AmoOperation::Min, 1'b1, 1'b0, $encoding); + +# SPDX-SnippetBegin +# SPDX-FileCopyrightText: 2017-2025 Contributors to the RISCV Sail Model +# SPDX-License-Identifier: BSD-2-Clause +sail(): | + { + if extension("A") then { + /* Get the address, X(rs1) (no offset). + * Some extensions perform additional checks on address validity. + */ + match ext_data_get_addr(rs1, zeros(), ReadWrite(Data, Data), width) { + Ext_DataAddr_Error(e) => { ext_handle_data_check_error(e); RETIRE_FAIL }, + Ext_DataAddr_OK(vaddr) => { + match translateAddr(vaddr, ReadWrite(Data, Data)) { + TR_Failure(e, _) => { handle_mem_exception(vaddr, e); RETIRE_FAIL }, + TR_Address(addr, _) => { + let eares : MemoryOpResult(unit) = match (width, sizeof(xlen)) { + (BYTE, _) => mem_write_ea(addr, 1, aq & rl, rl, true), + (HALF, _) => mem_write_ea(addr, 2, aq & rl, rl, true), + (WORD, _) => mem_write_ea(addr, 4, aq & rl, rl, true), + (DOUBLE, 64) => mem_write_ea(addr, 8, aq & rl, rl, true), + _ => internal_error(__FILE__, __LINE__, "Unexpected AMO width") + }; + let is_unsigned : bool = match op { + AMOMINU => true, + AMOMAXU => true, + _ => false + }; + let rs2_val : xlenbits = match width { + BYTE => if is_unsigned then zero_extend(X(rs2)[7..0]) else sign_extend(X(rs2)[7..0]), + HALF => if is_unsigned then zero_extend(X(rs2)[15..0]) else sign_extend(X(rs2)[15..0]), + WORD => if is_unsigned then zero_extend(X(rs2)[31..0]) else sign_extend(X(rs2)[31..0]), + DOUBLE => X(rs2) + }; + match (eares) { + MemException(e) => { handle_mem_exception(vaddr, e); RETIRE_FAIL }, + MemValue(_) => { + let mval : MemoryOpResult(xlenbits) = match (width, sizeof(xlen)) { + (BYTE, _) => extend_value(is_unsigned, mem_read(ReadWrite(Data, Data), addr, 1, aq, aq & rl, true)), + (HALF, _) => extend_value(is_unsigned, mem_read(ReadWrite(Data, Data), addr, 2, aq, aq & rl, true)), + (WORD, _) => extend_value(is_unsigned, mem_read(ReadWrite(Data, Data), addr, 4, aq, aq & rl, true)), + (DOUBLE, 64) => extend_value(is_unsigned, mem_read(ReadWrite(Data, Data), addr, 8, aq, aq & rl, true)), + _ => internal_error(__FILE__, __LINE__, "Unexpected AMO width") + }; + match (mval) { + MemException(e) => { handle_mem_exception(vaddr, e); RETIRE_FAIL }, + MemValue(loaded) => { + let result : xlenbits = + match op { + AMOSWAP => rs2_val, + AMOADD => rs2_val + loaded, + AMOXOR => rs2_val ^ loaded, + AMOAND => rs2_val & loaded, + AMOOR => rs2_val | loaded, + + /* These operations convert bitvectors to integer values using [un]signed, + * and back using to_bits(). + */ + AMOMIN => to_bits(sizeof(xlen), min(signed(rs2_val), signed(loaded))), + AMOMAX => to_bits(sizeof(xlen), max(signed(rs2_val), signed(loaded))), + AMOMINU => to_bits(sizeof(xlen), min(unsigned(rs2_val), unsigned(loaded))), + AMOMAXU => to_bits(sizeof(xlen), max(unsigned(rs2_val), unsigned(loaded))) + }; + let rval : xlenbits = match width { + BYTE => sign_extend(loaded[7..0]), + HALF => sign_extend(loaded[15..0]), + WORD => sign_extend(loaded[31..0]), + DOUBLE => loaded + }; + let wval : MemoryOpResult(bool) = match (width, sizeof(xlen)) { + (BYTE, _) => mem_write_value(addr, 1, result[7..0], aq & rl, rl, true), + (HALF, _) => mem_write_value(addr, 2, result[15..0], aq & rl, rl, true), + (WORD, _) => mem_write_value(addr, 4, result[31..0], aq & rl, rl, true), + (DOUBLE, 64) => mem_write_value(addr, 8, result, aq & rl, rl, true), + _ => internal_error(__FILE__, __LINE__, "Unexpected AMO width") + }; + match (wval) { + MemValue(true) => { X(rd) = rval; RETIRE_SUCCESS }, + MemValue(false) => { internal_error(__FILE__, __LINE__, "AMO got false from mem_write_value") }, + MemException(e) => { handle_mem_exception(vaddr, e); RETIRE_FAIL } + } + } + } + } + } + } + } + } + } + } else { + handle_illegal(); + RETIRE_FAIL + } + } + +# SPDX-SnippetEnd diff --git a/spec/std/isa/inst/Zaamo/amomin.d.aqrl.yaml b/spec/std/isa/inst/Zaamo/amomin.d.aqrl.yaml new file mode 100644 index 0000000000..d9d56d2786 --- /dev/null +++ b/spec/std/isa/inst/Zaamo/amomin.d.aqrl.yaml @@ -0,0 +1,142 @@ +# Copyright (c) Qualcomm Technologies, Inc. and/or its subsidiaries. + +# WARNING: This file is auto-generated from spec/std/isa/inst/Zaamo/amomin.SIZE.AQRL.layout# Copyright (c) Abhijit Das(Sukuna0007Abhi) +# SPDX-License-Identifier: BSD-3-Clause-Clear + +# yaml-language-server: $schema=../../../../schemas/inst_schema.json + +$schema: "inst_schema.json#" +kind: instruction +name: amomin.d.aqrl +long_name: Atomic MIN doubleword (acquire-release) +description: | + Atomically with acquire and release ordering: + + * Load the doubleword at address _xs1_ + * Write the loaded value into _xd_ + * Signed compare the value of register _xs2_ to the loaded value, and select the minimum value + * Write the minimum to the address in _xs1_ +definedBy: Zaamo +base: 64 +assembly: xd, xs2, (xs1) +encoding: + match: 1000011----------011-----0101111 + variables: + - name: xs2 + location: 24-20 + - name: xs1 + location: 19-15 + - name: xd + location: 11-7 +access: + s: always + u: always + vs: always + vu: always +operation(): | + if (!implemented?(ExtensionName::A) || (MISA_CSR_IMPLEMENTED && (CSR[misa].A == 1'b0))) { + raise (ExceptionCode::IllegalInstruction, mode(), $encoding); + } + + memory_model_acquire(); + + XReg virtual_address = X[xs1]; + X[xd] = amo<64>(virtual_address, X[xs2], AmoOperation::Min, 1'b1, 1'b1, $encoding); + + memory_model_release(); + +# SPDX-SnippetBegin +# SPDX-FileCopyrightText: 2017-2025 Contributors to the RISCV Sail Model +# SPDX-License-Identifier: BSD-2-Clause +sail(): | + { + if extension("A") then { + /* Get the address, X(rs1) (no offset). + * Some extensions perform additional checks on address validity. + */ + match ext_data_get_addr(rs1, zeros(), ReadWrite(Data, Data), width) { + Ext_DataAddr_Error(e) => { ext_handle_data_check_error(e); RETIRE_FAIL }, + Ext_DataAddr_OK(vaddr) => { + match translateAddr(vaddr, ReadWrite(Data, Data)) { + TR_Failure(e, _) => { handle_mem_exception(vaddr, e); RETIRE_FAIL }, + TR_Address(addr, _) => { + let eares : MemoryOpResult(unit) = match (width, sizeof(xlen)) { + (BYTE, _) => mem_write_ea(addr, 1, aq & rl, rl, true), + (HALF, _) => mem_write_ea(addr, 2, aq & rl, rl, true), + (WORD, _) => mem_write_ea(addr, 4, aq & rl, rl, true), + (DOUBLE, 64) => mem_write_ea(addr, 8, aq & rl, rl, true), + _ => internal_error(__FILE__, __LINE__, "Unexpected AMO width") + }; + let is_unsigned : bool = match op { + AMOMINU => true, + AMOMAXU => true, + _ => false + }; + let rs2_val : xlenbits = match width { + BYTE => if is_unsigned then zero_extend(X(rs2)[7..0]) else sign_extend(X(rs2)[7..0]), + HALF => if is_unsigned then zero_extend(X(rs2)[15..0]) else sign_extend(X(rs2)[15..0]), + WORD => if is_unsigned then zero_extend(X(rs2)[31..0]) else sign_extend(X(rs2)[31..0]), + DOUBLE => X(rs2) + }; + match (eares) { + MemException(e) => { handle_mem_exception(vaddr, e); RETIRE_FAIL }, + MemValue(_) => { + let mval : MemoryOpResult(xlenbits) = match (width, sizeof(xlen)) { + (BYTE, _) => extend_value(is_unsigned, mem_read(ReadWrite(Data, Data), addr, 1, aq, aq & rl, true)), + (HALF, _) => extend_value(is_unsigned, mem_read(ReadWrite(Data, Data), addr, 2, aq, aq & rl, true)), + (WORD, _) => extend_value(is_unsigned, mem_read(ReadWrite(Data, Data), addr, 4, aq, aq & rl, true)), + (DOUBLE, 64) => extend_value(is_unsigned, mem_read(ReadWrite(Data, Data), addr, 8, aq, aq & rl, true)), + _ => internal_error(__FILE__, __LINE__, "Unexpected AMO width") + }; + match (mval) { + MemException(e) => { handle_mem_exception(vaddr, e); RETIRE_FAIL }, + MemValue(loaded) => { + let result : xlenbits = + match op { + AMOSWAP => rs2_val, + AMOADD => rs2_val + loaded, + AMOXOR => rs2_val ^ loaded, + AMOAND => rs2_val & loaded, + AMOOR => rs2_val | loaded, + + /* These operations convert bitvectors to integer values using [un]signed, + * and back using to_bits(). + */ + AMOMIN => to_bits(sizeof(xlen), min(signed(rs2_val), signed(loaded))), + AMOMAX => to_bits(sizeof(xlen), max(signed(rs2_val), signed(loaded))), + AMOMINU => to_bits(sizeof(xlen), min(unsigned(rs2_val), unsigned(loaded))), + AMOMAXU => to_bits(sizeof(xlen), max(unsigned(rs2_val), unsigned(loaded))) + }; + let rval : xlenbits = match width { + BYTE => sign_extend(loaded[7..0]), + HALF => sign_extend(loaded[15..0]), + WORD => sign_extend(loaded[31..0]), + DOUBLE => loaded + }; + let wval : MemoryOpResult(bool) = match (width, sizeof(xlen)) { + (BYTE, _) => mem_write_value(addr, 1, result[7..0], aq & rl, rl, true), + (HALF, _) => mem_write_value(addr, 2, result[15..0], aq & rl, rl, true), + (WORD, _) => mem_write_value(addr, 4, result[31..0], aq & rl, rl, true), + (DOUBLE, 64) => mem_write_value(addr, 8, result, aq & rl, rl, true), + _ => internal_error(__FILE__, __LINE__, "Unexpected AMO width") + }; + match (wval) { + MemValue(true) => { X(rd) = rval; RETIRE_SUCCESS }, + MemValue(false) => { internal_error(__FILE__, __LINE__, "AMO got false from mem_write_value") }, + MemException(e) => { handle_mem_exception(vaddr, e); RETIRE_FAIL } + } + } + } + } + } + } + } + } + } + } else { + handle_illegal(); + RETIRE_FAIL + } + } + +# SPDX-SnippetEnd diff --git a/spec/std/isa/inst/Zaamo/amomin.d.rl.yaml b/spec/std/isa/inst/Zaamo/amomin.d.rl.yaml new file mode 100644 index 0000000000..a58a48b6e8 --- /dev/null +++ b/spec/std/isa/inst/Zaamo/amomin.d.rl.yaml @@ -0,0 +1,140 @@ +# Copyright (c) Qualcomm Technologies, Inc. and/or its subsidiaries. + +# WARNING: This file is auto-generated from spec/std/isa/inst/Zaamo/amomin.SIZE.AQRL.layout# Copyright (c) Abhijit Das(Sukuna0007Abhi) +# SPDX-License-Identifier: BSD-3-Clause-Clear + +# yaml-language-server: $schema=../../../../schemas/inst_schema.json + +$schema: "inst_schema.json#" +kind: instruction +name: amomin.d.rl +long_name: Atomic MIN doubleword (release) +description: | + Atomically with release ordering: + + * Load the doubleword at address _xs1_ + * Write the loaded value into _xd_ + * Signed compare the value of register _xs2_ to the loaded value, and select the minimum value + * Write the minimum to the address in _xs1_ +definedBy: Zaamo +base: 64 +assembly: xd, xs2, (xs1) +encoding: + match: 1000001----------011-----0101111 + variables: + - name: xs2 + location: 24-20 + - name: xs1 + location: 19-15 + - name: xd + location: 11-7 +access: + s: always + u: always + vs: always + vu: always +operation(): | + if (!implemented?(ExtensionName::A) || (MISA_CSR_IMPLEMENTED && (CSR[misa].A == 1'b0))) { + raise (ExceptionCode::IllegalInstruction, mode(), $encoding); + } + + XReg virtual_address = X[xs1]; + X[xd] = amo<64>(virtual_address, X[xs2], AmoOperation::Min, 1'b0, 1'b1, $encoding); + + memory_model_release(); + +# SPDX-SnippetBegin +# SPDX-FileCopyrightText: 2017-2025 Contributors to the RISCV Sail Model +# SPDX-License-Identifier: BSD-2-Clause +sail(): | + { + if extension("A") then { + /* Get the address, X(rs1) (no offset). + * Some extensions perform additional checks on address validity. + */ + match ext_data_get_addr(rs1, zeros(), ReadWrite(Data, Data), width) { + Ext_DataAddr_Error(e) => { ext_handle_data_check_error(e); RETIRE_FAIL }, + Ext_DataAddr_OK(vaddr) => { + match translateAddr(vaddr, ReadWrite(Data, Data)) { + TR_Failure(e, _) => { handle_mem_exception(vaddr, e); RETIRE_FAIL }, + TR_Address(addr, _) => { + let eares : MemoryOpResult(unit) = match (width, sizeof(xlen)) { + (BYTE, _) => mem_write_ea(addr, 1, aq & rl, rl, true), + (HALF, _) => mem_write_ea(addr, 2, aq & rl, rl, true), + (WORD, _) => mem_write_ea(addr, 4, aq & rl, rl, true), + (DOUBLE, 64) => mem_write_ea(addr, 8, aq & rl, rl, true), + _ => internal_error(__FILE__, __LINE__, "Unexpected AMO width") + }; + let is_unsigned : bool = match op { + AMOMINU => true, + AMOMAXU => true, + _ => false + }; + let rs2_val : xlenbits = match width { + BYTE => if is_unsigned then zero_extend(X(rs2)[7..0]) else sign_extend(X(rs2)[7..0]), + HALF => if is_unsigned then zero_extend(X(rs2)[15..0]) else sign_extend(X(rs2)[15..0]), + WORD => if is_unsigned then zero_extend(X(rs2)[31..0]) else sign_extend(X(rs2)[31..0]), + DOUBLE => X(rs2) + }; + match (eares) { + MemException(e) => { handle_mem_exception(vaddr, e); RETIRE_FAIL }, + MemValue(_) => { + let mval : MemoryOpResult(xlenbits) = match (width, sizeof(xlen)) { + (BYTE, _) => extend_value(is_unsigned, mem_read(ReadWrite(Data, Data), addr, 1, aq, aq & rl, true)), + (HALF, _) => extend_value(is_unsigned, mem_read(ReadWrite(Data, Data), addr, 2, aq, aq & rl, true)), + (WORD, _) => extend_value(is_unsigned, mem_read(ReadWrite(Data, Data), addr, 4, aq, aq & rl, true)), + (DOUBLE, 64) => extend_value(is_unsigned, mem_read(ReadWrite(Data, Data), addr, 8, aq, aq & rl, true)), + _ => internal_error(__FILE__, __LINE__, "Unexpected AMO width") + }; + match (mval) { + MemException(e) => { handle_mem_exception(vaddr, e); RETIRE_FAIL }, + MemValue(loaded) => { + let result : xlenbits = + match op { + AMOSWAP => rs2_val, + AMOADD => rs2_val + loaded, + AMOXOR => rs2_val ^ loaded, + AMOAND => rs2_val & loaded, + AMOOR => rs2_val | loaded, + + /* These operations convert bitvectors to integer values using [un]signed, + * and back using to_bits(). + */ + AMOMIN => to_bits(sizeof(xlen), min(signed(rs2_val), signed(loaded))), + AMOMAX => to_bits(sizeof(xlen), max(signed(rs2_val), signed(loaded))), + AMOMINU => to_bits(sizeof(xlen), min(unsigned(rs2_val), unsigned(loaded))), + AMOMAXU => to_bits(sizeof(xlen), max(unsigned(rs2_val), unsigned(loaded))) + }; + let rval : xlenbits = match width { + BYTE => sign_extend(loaded[7..0]), + HALF => sign_extend(loaded[15..0]), + WORD => sign_extend(loaded[31..0]), + DOUBLE => loaded + }; + let wval : MemoryOpResult(bool) = match (width, sizeof(xlen)) { + (BYTE, _) => mem_write_value(addr, 1, result[7..0], aq & rl, rl, true), + (HALF, _) => mem_write_value(addr, 2, result[15..0], aq & rl, rl, true), + (WORD, _) => mem_write_value(addr, 4, result[31..0], aq & rl, rl, true), + (DOUBLE, 64) => mem_write_value(addr, 8, result, aq & rl, rl, true), + _ => internal_error(__FILE__, __LINE__, "Unexpected AMO width") + }; + match (wval) { + MemValue(true) => { X(rd) = rval; RETIRE_SUCCESS }, + MemValue(false) => { internal_error(__FILE__, __LINE__, "AMO got false from mem_write_value") }, + MemException(e) => { handle_mem_exception(vaddr, e); RETIRE_FAIL } + } + } + } + } + } + } + } + } + } + } else { + handle_illegal(); + RETIRE_FAIL + } + } + +# SPDX-SnippetEnd diff --git a/spec/std/isa/inst/Zaamo/amomin.d.yaml b/spec/std/isa/inst/Zaamo/amomin.d.yaml index 746c1d65f9..9968c8e653 100644 --- a/spec/std/isa/inst/Zaamo/amomin.d.yaml +++ b/spec/std/isa/inst/Zaamo/amomin.d.yaml @@ -1,4 +1,6 @@ # Copyright (c) Qualcomm Technologies, Inc. and/or its subsidiaries. + +# WARNING: This file is auto-generated from spec/std/isa/inst/Zaamo/amomin.SIZE.AQRL.layout# Copyright (c) Abhijit Das(Sukuna0007Abhi) # SPDX-License-Identifier: BSD-3-Clause-Clear # yaml-language-server: $schema=../../../../schemas/inst_schema.json @@ -18,12 +20,8 @@ definedBy: Zaamo base: 64 assembly: xd, xs2, (xs1) encoding: - match: 10000------------011-----0101111 + match: 1000000----------011-----0101111 variables: - - name: aq - location: 26 - - name: rl - location: 25 - name: xs2 location: 24-20 - name: xs1 @@ -36,15 +34,12 @@ access: vs: always vu: always operation(): | - if (implemented?(ExtensionName::A) && (CSR[misa].A == 1'b0)) { - # even though this is a memory operation, the exception occurs before that would be known, - # so mode() is the correct reporting mode rathat than effective_ldst_mode() + if (!implemented?(ExtensionName::A) || (MISA_CSR_IMPLEMENTED && (CSR[misa].A == 1'b0))) { raise (ExceptionCode::IllegalInstruction, mode(), $encoding); } XReg virtual_address = X[xs1]; - - X[xd] = amo<64>(virtual_address, X[xs2], AmoOperation::Min, aq, rl, $encoding); + X[xd] = amo<64>(virtual_address, X[xs2], AmoOperation::Min, 1'b0, 1'b0, $encoding); # SPDX-SnippetBegin # SPDX-FileCopyrightText: 2017-2025 Contributors to the RISCV Sail Model diff --git a/spec/std/isa/inst/Zaamo/amomin.w.aq.yaml b/spec/std/isa/inst/Zaamo/amomin.w.aq.yaml new file mode 100644 index 0000000000..1765b6cbe2 --- /dev/null +++ b/spec/std/isa/inst/Zaamo/amomin.w.aq.yaml @@ -0,0 +1,139 @@ +# Copyright (c) Qualcomm Technologies, Inc. and/or its subsidiaries. + +# WARNING: This file is auto-generated from spec/std/isa/inst/Zaamo/amomin.SIZE.AQRL.layout# Copyright (c) Abhijit Das(Sukuna0007Abhi) +# SPDX-License-Identifier: BSD-3-Clause-Clear + +# yaml-language-server: $schema=../../../../schemas/inst_schema.json + +$schema: "inst_schema.json#" +kind: instruction +name: amomin.w.aq +long_name: Atomic MIN word (acquire) +description: | + Atomically with acquire ordering: + + * Load the word at address _xs1_ + * Write the sign-extended value into _xd_ + * Signed compare the least-significant word of register _xs2_ to the loaded value, and select the minimum value + * Write the minimum to the address in _xs1_ +definedBy: Zaamo +assembly: xd, xs2, (xs1) +encoding: + match: 1000010----------010-----0101111 + variables: + - name: xs2 + location: 24-20 + - name: xs1 + location: 19-15 + - name: xd + location: 11-7 +access: + s: always + u: always + vs: always + vu: always +operation(): | + if (!implemented?(ExtensionName::A) || (MISA_CSR_IMPLEMENTED && (CSR[misa].A == 1'b0))) { + raise (ExceptionCode::IllegalInstruction, mode(), $encoding); + } + + memory_model_acquire(); + + XReg virtual_address = X[xs1]; + X[xd] = amo<32>(virtual_address, X[xs2][31:0], AmoOperation::Min, 1'b1, 1'b0, $encoding); + +# SPDX-SnippetBegin +# SPDX-FileCopyrightText: 2017-2025 Contributors to the RISCV Sail Model +# SPDX-License-Identifier: BSD-2-Clause +sail(): | + { + if extension("A") then { + /* Get the address, X(rs1) (no offset). + * Some extensions perform additional checks on address validity. + */ + match ext_data_get_addr(rs1, zeros(), ReadWrite(Data, Data), width) { + Ext_DataAddr_Error(e) => { ext_handle_data_check_error(e); RETIRE_FAIL }, + Ext_DataAddr_OK(vaddr) => { + match translateAddr(vaddr, ReadWrite(Data, Data)) { + TR_Failure(e, _) => { handle_mem_exception(vaddr, e); RETIRE_FAIL }, + TR_Address(addr, _) => { + let eares : MemoryOpResult(unit) = match (width, sizeof(xlen)) { + (BYTE, _) => mem_write_ea(addr, 1, aq & rl, rl, true), + (HALF, _) => mem_write_ea(addr, 2, aq & rl, rl, true), + (WORD, _) => mem_write_ea(addr, 4, aq & rl, rl, true), + (DOUBLE, 64) => mem_write_ea(addr, 8, aq & rl, rl, true), + _ => internal_error(__FILE__, __LINE__, "Unexpected AMO width") + }; + let is_unsigned : bool = match op { + AMOMINU => true, + AMOMAXU => true, + _ => false + }; + let rs2_val : xlenbits = match width { + BYTE => if is_unsigned then zero_extend(X(rs2)[7..0]) else sign_extend(X(rs2)[7..0]), + HALF => if is_unsigned then zero_extend(X(rs2)[15..0]) else sign_extend(X(rs2)[15..0]), + WORD => if is_unsigned then zero_extend(X(rs2)[31..0]) else sign_extend(X(rs2)[31..0]), + DOUBLE => X(rs2) + }; + match (eares) { + MemException(e) => { handle_mem_exception(vaddr, e); RETIRE_FAIL }, + MemValue(_) => { + let mval : MemoryOpResult(xlenbits) = match (width, sizeof(xlen)) { + (BYTE, _) => extend_value(is_unsigned, mem_read(ReadWrite(Data, Data), addr, 1, aq, aq & rl, true)), + (HALF, _) => extend_value(is_unsigned, mem_read(ReadWrite(Data, Data), addr, 2, aq, aq & rl, true)), + (WORD, _) => extend_value(is_unsigned, mem_read(ReadWrite(Data, Data), addr, 4, aq, aq & rl, true)), + (DOUBLE, 64) => extend_value(is_unsigned, mem_read(ReadWrite(Data, Data), addr, 8, aq, aq & rl, true)), + _ => internal_error(__FILE__, __LINE__, "Unexpected AMO width") + }; + match (mval) { + MemException(e) => { handle_mem_exception(vaddr, e); RETIRE_FAIL }, + MemValue(loaded) => { + let result : xlenbits = + match op { + AMOSWAP => rs2_val, + AMOADD => rs2_val + loaded, + AMOXOR => rs2_val ^ loaded, + AMOAND => rs2_val & loaded, + AMOOR => rs2_val | loaded, + + /* These operations convert bitvectors to integer values using [un]signed, + * and back using to_bits(). + */ + AMOMIN => to_bits(sizeof(xlen), min(signed(rs2_val), signed(loaded))), + AMOMAX => to_bits(sizeof(xlen), max(signed(rs2_val), signed(loaded))), + AMOMINU => to_bits(sizeof(xlen), min(unsigned(rs2_val), unsigned(loaded))), + AMOMAXU => to_bits(sizeof(xlen), max(unsigned(rs2_val), unsigned(loaded))) + }; + let rval : xlenbits = match width { + BYTE => sign_extend(loaded[7..0]), + HALF => sign_extend(loaded[15..0]), + WORD => sign_extend(loaded[31..0]), + DOUBLE => loaded + }; + let wval : MemoryOpResult(bool) = match (width, sizeof(xlen)) { + (BYTE, _) => mem_write_value(addr, 1, result[7..0], aq & rl, rl, true), + (HALF, _) => mem_write_value(addr, 2, result[15..0], aq & rl, rl, true), + (WORD, _) => mem_write_value(addr, 4, result[31..0], aq & rl, rl, true), + (DOUBLE, 64) => mem_write_value(addr, 8, result, aq & rl, rl, true), + _ => internal_error(__FILE__, __LINE__, "Unexpected AMO width") + }; + match (wval) { + MemValue(true) => { X(rd) = rval; RETIRE_SUCCESS }, + MemValue(false) => { internal_error(__FILE__, __LINE__, "AMO got false from mem_write_value") }, + MemException(e) => { handle_mem_exception(vaddr, e); RETIRE_FAIL } + } + } + } + } + } + } + } + } + } + } else { + handle_illegal(); + RETIRE_FAIL + } + } + +# SPDX-SnippetEnd diff --git a/spec/std/isa/inst/Zaamo/amomin.w.aqrl.yaml b/spec/std/isa/inst/Zaamo/amomin.w.aqrl.yaml new file mode 100644 index 0000000000..1ba6b55cf6 --- /dev/null +++ b/spec/std/isa/inst/Zaamo/amomin.w.aqrl.yaml @@ -0,0 +1,141 @@ +# Copyright (c) Qualcomm Technologies, Inc. and/or its subsidiaries. + +# WARNING: This file is auto-generated from spec/std/isa/inst/Zaamo/amomin.SIZE.AQRL.layout# Copyright (c) Abhijit Das(Sukuna0007Abhi) +# SPDX-License-Identifier: BSD-3-Clause-Clear + +# yaml-language-server: $schema=../../../../schemas/inst_schema.json + +$schema: "inst_schema.json#" +kind: instruction +name: amomin.w.aqrl +long_name: Atomic MIN word (acquire-release) +description: | + Atomically with acquire and release ordering: + + * Load the word at address _xs1_ + * Write the sign-extended value into _xd_ + * Signed compare the least-significant word of register _xs2_ to the loaded value, and select the minimum value + * Write the minimum to the address in _xs1_ +definedBy: Zaamo +assembly: xd, xs2, (xs1) +encoding: + match: 1000011----------010-----0101111 + variables: + - name: xs2 + location: 24-20 + - name: xs1 + location: 19-15 + - name: xd + location: 11-7 +access: + s: always + u: always + vs: always + vu: always +operation(): | + if (!implemented?(ExtensionName::A) || (MISA_CSR_IMPLEMENTED && (CSR[misa].A == 1'b0))) { + raise (ExceptionCode::IllegalInstruction, mode(), $encoding); + } + + memory_model_acquire(); + + XReg virtual_address = X[xs1]; + X[xd] = amo<32>(virtual_address, X[xs2][31:0], AmoOperation::Min, 1'b1, 1'b1, $encoding); + + memory_model_release(); + +# SPDX-SnippetBegin +# SPDX-FileCopyrightText: 2017-2025 Contributors to the RISCV Sail Model +# SPDX-License-Identifier: BSD-2-Clause +sail(): | + { + if extension("A") then { + /* Get the address, X(rs1) (no offset). + * Some extensions perform additional checks on address validity. + */ + match ext_data_get_addr(rs1, zeros(), ReadWrite(Data, Data), width) { + Ext_DataAddr_Error(e) => { ext_handle_data_check_error(e); RETIRE_FAIL }, + Ext_DataAddr_OK(vaddr) => { + match translateAddr(vaddr, ReadWrite(Data, Data)) { + TR_Failure(e, _) => { handle_mem_exception(vaddr, e); RETIRE_FAIL }, + TR_Address(addr, _) => { + let eares : MemoryOpResult(unit) = match (width, sizeof(xlen)) { + (BYTE, _) => mem_write_ea(addr, 1, aq & rl, rl, true), + (HALF, _) => mem_write_ea(addr, 2, aq & rl, rl, true), + (WORD, _) => mem_write_ea(addr, 4, aq & rl, rl, true), + (DOUBLE, 64) => mem_write_ea(addr, 8, aq & rl, rl, true), + _ => internal_error(__FILE__, __LINE__, "Unexpected AMO width") + }; + let is_unsigned : bool = match op { + AMOMINU => true, + AMOMAXU => true, + _ => false + }; + let rs2_val : xlenbits = match width { + BYTE => if is_unsigned then zero_extend(X(rs2)[7..0]) else sign_extend(X(rs2)[7..0]), + HALF => if is_unsigned then zero_extend(X(rs2)[15..0]) else sign_extend(X(rs2)[15..0]), + WORD => if is_unsigned then zero_extend(X(rs2)[31..0]) else sign_extend(X(rs2)[31..0]), + DOUBLE => X(rs2) + }; + match (eares) { + MemException(e) => { handle_mem_exception(vaddr, e); RETIRE_FAIL }, + MemValue(_) => { + let mval : MemoryOpResult(xlenbits) = match (width, sizeof(xlen)) { + (BYTE, _) => extend_value(is_unsigned, mem_read(ReadWrite(Data, Data), addr, 1, aq, aq & rl, true)), + (HALF, _) => extend_value(is_unsigned, mem_read(ReadWrite(Data, Data), addr, 2, aq, aq & rl, true)), + (WORD, _) => extend_value(is_unsigned, mem_read(ReadWrite(Data, Data), addr, 4, aq, aq & rl, true)), + (DOUBLE, 64) => extend_value(is_unsigned, mem_read(ReadWrite(Data, Data), addr, 8, aq, aq & rl, true)), + _ => internal_error(__FILE__, __LINE__, "Unexpected AMO width") + }; + match (mval) { + MemException(e) => { handle_mem_exception(vaddr, e); RETIRE_FAIL }, + MemValue(loaded) => { + let result : xlenbits = + match op { + AMOSWAP => rs2_val, + AMOADD => rs2_val + loaded, + AMOXOR => rs2_val ^ loaded, + AMOAND => rs2_val & loaded, + AMOOR => rs2_val | loaded, + + /* These operations convert bitvectors to integer values using [un]signed, + * and back using to_bits(). + */ + AMOMIN => to_bits(sizeof(xlen), min(signed(rs2_val), signed(loaded))), + AMOMAX => to_bits(sizeof(xlen), max(signed(rs2_val), signed(loaded))), + AMOMINU => to_bits(sizeof(xlen), min(unsigned(rs2_val), unsigned(loaded))), + AMOMAXU => to_bits(sizeof(xlen), max(unsigned(rs2_val), unsigned(loaded))) + }; + let rval : xlenbits = match width { + BYTE => sign_extend(loaded[7..0]), + HALF => sign_extend(loaded[15..0]), + WORD => sign_extend(loaded[31..0]), + DOUBLE => loaded + }; + let wval : MemoryOpResult(bool) = match (width, sizeof(xlen)) { + (BYTE, _) => mem_write_value(addr, 1, result[7..0], aq & rl, rl, true), + (HALF, _) => mem_write_value(addr, 2, result[15..0], aq & rl, rl, true), + (WORD, _) => mem_write_value(addr, 4, result[31..0], aq & rl, rl, true), + (DOUBLE, 64) => mem_write_value(addr, 8, result, aq & rl, rl, true), + _ => internal_error(__FILE__, __LINE__, "Unexpected AMO width") + }; + match (wval) { + MemValue(true) => { X(rd) = rval; RETIRE_SUCCESS }, + MemValue(false) => { internal_error(__FILE__, __LINE__, "AMO got false from mem_write_value") }, + MemException(e) => { handle_mem_exception(vaddr, e); RETIRE_FAIL } + } + } + } + } + } + } + } + } + } + } else { + handle_illegal(); + RETIRE_FAIL + } + } + +# SPDX-SnippetEnd diff --git a/spec/std/isa/inst/Zaamo/amomin.w.rl.yaml b/spec/std/isa/inst/Zaamo/amomin.w.rl.yaml new file mode 100644 index 0000000000..095157d27a --- /dev/null +++ b/spec/std/isa/inst/Zaamo/amomin.w.rl.yaml @@ -0,0 +1,139 @@ +# Copyright (c) Qualcomm Technologies, Inc. and/or its subsidiaries. + +# WARNING: This file is auto-generated from spec/std/isa/inst/Zaamo/amomin.SIZE.AQRL.layout# Copyright (c) Abhijit Das(Sukuna0007Abhi) +# SPDX-License-Identifier: BSD-3-Clause-Clear + +# yaml-language-server: $schema=../../../../schemas/inst_schema.json + +$schema: "inst_schema.json#" +kind: instruction +name: amomin.w.rl +long_name: Atomic MIN word (release) +description: | + Atomically with release ordering: + + * Load the word at address _xs1_ + * Write the sign-extended value into _xd_ + * Signed compare the least-significant word of register _xs2_ to the loaded value, and select the minimum value + * Write the minimum to the address in _xs1_ +definedBy: Zaamo +assembly: xd, xs2, (xs1) +encoding: + match: 1000001----------010-----0101111 + variables: + - name: xs2 + location: 24-20 + - name: xs1 + location: 19-15 + - name: xd + location: 11-7 +access: + s: always + u: always + vs: always + vu: always +operation(): | + if (!implemented?(ExtensionName::A) || (MISA_CSR_IMPLEMENTED && (CSR[misa].A == 1'b0))) { + raise (ExceptionCode::IllegalInstruction, mode(), $encoding); + } + + XReg virtual_address = X[xs1]; + X[xd] = amo<32>(virtual_address, X[xs2][31:0], AmoOperation::Min, 1'b0, 1'b1, $encoding); + + memory_model_release(); + +# SPDX-SnippetBegin +# SPDX-FileCopyrightText: 2017-2025 Contributors to the RISCV Sail Model +# SPDX-License-Identifier: BSD-2-Clause +sail(): | + { + if extension("A") then { + /* Get the address, X(rs1) (no offset). + * Some extensions perform additional checks on address validity. + */ + match ext_data_get_addr(rs1, zeros(), ReadWrite(Data, Data), width) { + Ext_DataAddr_Error(e) => { ext_handle_data_check_error(e); RETIRE_FAIL }, + Ext_DataAddr_OK(vaddr) => { + match translateAddr(vaddr, ReadWrite(Data, Data)) { + TR_Failure(e, _) => { handle_mem_exception(vaddr, e); RETIRE_FAIL }, + TR_Address(addr, _) => { + let eares : MemoryOpResult(unit) = match (width, sizeof(xlen)) { + (BYTE, _) => mem_write_ea(addr, 1, aq & rl, rl, true), + (HALF, _) => mem_write_ea(addr, 2, aq & rl, rl, true), + (WORD, _) => mem_write_ea(addr, 4, aq & rl, rl, true), + (DOUBLE, 64) => mem_write_ea(addr, 8, aq & rl, rl, true), + _ => internal_error(__FILE__, __LINE__, "Unexpected AMO width") + }; + let is_unsigned : bool = match op { + AMOMINU => true, + AMOMAXU => true, + _ => false + }; + let rs2_val : xlenbits = match width { + BYTE => if is_unsigned then zero_extend(X(rs2)[7..0]) else sign_extend(X(rs2)[7..0]), + HALF => if is_unsigned then zero_extend(X(rs2)[15..0]) else sign_extend(X(rs2)[15..0]), + WORD => if is_unsigned then zero_extend(X(rs2)[31..0]) else sign_extend(X(rs2)[31..0]), + DOUBLE => X(rs2) + }; + match (eares) { + MemException(e) => { handle_mem_exception(vaddr, e); RETIRE_FAIL }, + MemValue(_) => { + let mval : MemoryOpResult(xlenbits) = match (width, sizeof(xlen)) { + (BYTE, _) => extend_value(is_unsigned, mem_read(ReadWrite(Data, Data), addr, 1, aq, aq & rl, true)), + (HALF, _) => extend_value(is_unsigned, mem_read(ReadWrite(Data, Data), addr, 2, aq, aq & rl, true)), + (WORD, _) => extend_value(is_unsigned, mem_read(ReadWrite(Data, Data), addr, 4, aq, aq & rl, true)), + (DOUBLE, 64) => extend_value(is_unsigned, mem_read(ReadWrite(Data, Data), addr, 8, aq, aq & rl, true)), + _ => internal_error(__FILE__, __LINE__, "Unexpected AMO width") + }; + match (mval) { + MemException(e) => { handle_mem_exception(vaddr, e); RETIRE_FAIL }, + MemValue(loaded) => { + let result : xlenbits = + match op { + AMOSWAP => rs2_val, + AMOADD => rs2_val + loaded, + AMOXOR => rs2_val ^ loaded, + AMOAND => rs2_val & loaded, + AMOOR => rs2_val | loaded, + + /* These operations convert bitvectors to integer values using [un]signed, + * and back using to_bits(). + */ + AMOMIN => to_bits(sizeof(xlen), min(signed(rs2_val), signed(loaded))), + AMOMAX => to_bits(sizeof(xlen), max(signed(rs2_val), signed(loaded))), + AMOMINU => to_bits(sizeof(xlen), min(unsigned(rs2_val), unsigned(loaded))), + AMOMAXU => to_bits(sizeof(xlen), max(unsigned(rs2_val), unsigned(loaded))) + }; + let rval : xlenbits = match width { + BYTE => sign_extend(loaded[7..0]), + HALF => sign_extend(loaded[15..0]), + WORD => sign_extend(loaded[31..0]), + DOUBLE => loaded + }; + let wval : MemoryOpResult(bool) = match (width, sizeof(xlen)) { + (BYTE, _) => mem_write_value(addr, 1, result[7..0], aq & rl, rl, true), + (HALF, _) => mem_write_value(addr, 2, result[15..0], aq & rl, rl, true), + (WORD, _) => mem_write_value(addr, 4, result[31..0], aq & rl, rl, true), + (DOUBLE, 64) => mem_write_value(addr, 8, result, aq & rl, rl, true), + _ => internal_error(__FILE__, __LINE__, "Unexpected AMO width") + }; + match (wval) { + MemValue(true) => { X(rd) = rval; RETIRE_SUCCESS }, + MemValue(false) => { internal_error(__FILE__, __LINE__, "AMO got false from mem_write_value") }, + MemException(e) => { handle_mem_exception(vaddr, e); RETIRE_FAIL } + } + } + } + } + } + } + } + } + } + } else { + handle_illegal(); + RETIRE_FAIL + } + } + +# SPDX-SnippetEnd diff --git a/spec/std/isa/inst/Zaamo/amomin.w.yaml b/spec/std/isa/inst/Zaamo/amomin.w.yaml index abd64f65e8..ac8f7a82d8 100644 --- a/spec/std/isa/inst/Zaamo/amomin.w.yaml +++ b/spec/std/isa/inst/Zaamo/amomin.w.yaml @@ -1,4 +1,6 @@ # Copyright (c) Qualcomm Technologies, Inc. and/or its subsidiaries. + +# WARNING: This file is auto-generated from spec/std/isa/inst/Zaamo/amomin.SIZE.AQRL.layout# Copyright (c) Abhijit Das(Sukuna0007Abhi) # SPDX-License-Identifier: BSD-3-Clause-Clear # yaml-language-server: $schema=../../../../schemas/inst_schema.json @@ -13,16 +15,12 @@ description: | * Load the word at address _xs1_ * Write the sign-extended value into _xd_ * Signed compare the least-significant word of register _xs2_ to the loaded value, and select the minimum value - * Write the result to the address in _xs1_ + * Write the minimum to the address in _xs1_ definedBy: Zaamo assembly: xd, xs2, (xs1) encoding: - match: 10000------------010-----0101111 + match: 1000000----------010-----0101111 variables: - - name: aq - location: 26 - - name: rl - location: 25 - name: xs2 location: 24-20 - name: xs1 @@ -35,15 +33,12 @@ access: vs: always vu: always operation(): | - if (implemented?(ExtensionName::A) && (CSR[misa].A == 1'b0)) { - # even though this is a memory operation, the exception occurs before that would be known, - # so mode() is the correct reporting mode rathat than effective_ldst_mode() + if (!implemented?(ExtensionName::A) || (MISA_CSR_IMPLEMENTED && (CSR[misa].A == 1'b0))) { raise (ExceptionCode::IllegalInstruction, mode(), $encoding); } XReg virtual_address = X[xs1]; - - X[xd] = amo<32>(virtual_address, X[xs2][31:0], AmoOperation::Min, aq, rl, $encoding); + X[xd] = amo<32>(virtual_address, X[xs2][31:0], AmoOperation::Min, 1'b0, 1'b0, $encoding); # SPDX-SnippetBegin # SPDX-FileCopyrightText: 2017-2025 Contributors to the RISCV Sail Model diff --git a/spec/std/isa/inst/Zaamo/amominu.SIZE.AQRL.layout b/spec/std/isa/inst/Zaamo/amominu.SIZE.AQRL.layout new file mode 100644 index 0000000000..54e0e3896d --- /dev/null +++ b/spec/std/isa/inst/Zaamo/amominu.SIZE.AQRL.layout @@ -0,0 +1,175 @@ +# Copyright (c) Qualcomm Technologies, Inc. and/or its subsidiaries. +# Copyright (c) Abhijit Das(Sukuna0007Abhi) +# SPDX-License-Identifier: BSD-3-Clause-Clear + +# yaml-language-server: $schema=../../../../schemas/inst_schema.json +<%- + raise "'size' must be defined as 'b', 'h', 'w', or 'd'" unless %w[b h w d].include?(size) + raise "'aq' must be defined as true or false" unless [true, false].include?(aq) + raise "'rl' must be defined as true or false" unless [true, false].include?(rl) + + size_info = { + "b" => { name: "byte", bits: 8, funct3: "000", operation_bits: "8" }, + "h" => { name: "halfword", bits: 16, funct3: "001", operation_bits: "16" }, + "w" => { name: "word", bits: 32, funct3: "010", operation_bits: "32" }, + "d" => { name: "doubleword", bits: 64, funct3: "011", operation_bits: "64" } + } + + current_size = size_info[size] + + # Generate instruction name suffix based on aq/rl + aq_rl_suffix = "" + if aq && rl + aq_rl_suffix = ".aqrl" + elsif aq + aq_rl_suffix = ".aq" + elsif rl + aq_rl_suffix = ".rl" + end + + # Generate match string with fixed aq/rl bits + aq_bit = aq ? "1" : "0" + rl_bit = rl ? "1" : "0" +-%> + +$schema: "inst_schema.json#" +kind: instruction +name: amominu.<%= size %><%= aq_rl_suffix %> +long_name: Atomic MIN unsigned <%= current_size[:name] %><%= aq && rl ? " (acquire-release)" : (aq ? " (acquire)" : (rl ? " (release)" : "")) %> +description: | + Atomically<%= aq && rl ? " with acquire and release ordering" : (aq ? " with acquire ordering" : (rl ? " with release ordering" : "")) %>: + + * Load the <%= current_size[:name] %> at address _xs1_ + * Write the <%= %w[b h w].include?(size) ? "sign-extended value" : "loaded value" %> into _xd_ + * Unsigned compare the <%= %w[b h w].include?(size) ? "least-significant #{current_size[:name]} of register" : "value of register" %> _xs2_ to the loaded value, and select the minimum value + * Write the minimum to the address in _xs1_ +definedBy: <%= %w[b h].include?(size) ? "Zabha" : "Zaamo" %> +<%- if size == "d" -%> +base: 64 +<%- end -%> +assembly: xd, xs2, (xs1) +encoding: + match: 11000<%= aq_bit %><%= rl_bit %>----------<%= current_size[:funct3] %>-----0101111 + variables: + - name: xs2 + location: 24-20 + - name: xs1 + location: 19-15 + - name: xd + location: 11-7 +access: + s: always + u: always + vs: always + vu: always +operation(): | + if (!implemented?(ExtensionName::A) || (MISA_CSR_IMPLEMENTED && (CSR[misa].A == 1'b0))) { + raise (ExceptionCode::IllegalInstruction, mode(), $encoding); + } + +<% if aq -%> + memory_model_acquire(); + +<% end -%> + XReg virtual_address = X[xs1]; + X[xd] = amo<<%= current_size[:operation_bits] %>>(virtual_address, X[xs2]<%= %w[b h w].include?(size) ? "[#{current_size[:bits]-1}:0]" : "" %>, AmoOperation::Minu, <%= aq ? "1'b1" : "1'b0" %>, <%= rl ? "1'b1" : "1'b0" %>, $encoding); +<% if rl -%> + + memory_model_release(); +<% end -%> + +# SPDX-SnippetBegin +# SPDX-FileCopyrightText: 2017-2025 Contributors to the RISCV Sail Model +# SPDX-License-Identifier: BSD-2-Clause +sail(): | + { + if extension("A") then { + /* Get the address, X(rs1) (no offset). + * Some extensions perform additional checks on address validity. + */ + match ext_data_get_addr(rs1, zeros(), ReadWrite(Data, Data), width) { + Ext_DataAddr_Error(e) => { ext_handle_data_check_error(e); RETIRE_FAIL }, + Ext_DataAddr_OK(vaddr) => { + match translateAddr(vaddr, ReadWrite(Data, Data)) { + TR_Failure(e, _) => { handle_mem_exception(vaddr, e); RETIRE_FAIL }, + TR_Address(addr, _) => { + let eares : MemoryOpResult(unit) = match (width, sizeof(xlen)) { + (BYTE, _) => mem_write_ea(addr, 1, aq & rl, rl, true), + (HALF, _) => mem_write_ea(addr, 2, aq & rl, rl, true), + (WORD, _) => mem_write_ea(addr, 4, aq & rl, rl, true), + (DOUBLE, 64) => mem_write_ea(addr, 8, aq & rl, rl, true), + _ => internal_error(__FILE__, __LINE__, "Unexpected AMO width") + }; + let is_unsigned : bool = match op { + AMOMINU => true, + AMOMAXU => true, + _ => false + }; + let rs2_val : xlenbits = match width { + BYTE => if is_unsigned then zero_extend(X(rs2)[7..0]) else sign_extend(X(rs2)[7..0]), + HALF => if is_unsigned then zero_extend(X(rs2)[15..0]) else sign_extend(X(rs2)[15..0]), + WORD => if is_unsigned then zero_extend(X(rs2)[31..0]) else sign_extend(X(rs2)[31..0]), + DOUBLE => X(rs2) + }; + match (eares) { + MemException(e) => { handle_mem_exception(vaddr, e); RETIRE_FAIL }, + MemValue(_) => { + let mval : MemoryOpResult(xlenbits) = match (width, sizeof(xlen)) { + (BYTE, _) => extend_value(is_unsigned, mem_read(ReadWrite(Data, Data), addr, 1, aq, aq & rl, true)), + (HALF, _) => extend_value(is_unsigned, mem_read(ReadWrite(Data, Data), addr, 2, aq, aq & rl, true)), + (WORD, _) => extend_value(is_unsigned, mem_read(ReadWrite(Data, Data), addr, 4, aq, aq & rl, true)), + (DOUBLE, 64) => extend_value(is_unsigned, mem_read(ReadWrite(Data, Data), addr, 8, aq, aq & rl, true)), + _ => internal_error(__FILE__, __LINE__, "Unexpected AMO width") + }; + match (mval) { + MemException(e) => { handle_mem_exception(vaddr, e); RETIRE_FAIL }, + MemValue(loaded) => { + let result : xlenbits = + match op { + AMOSWAP => rs2_val, + AMOADD => rs2_val + loaded, + AMOXOR => rs2_val ^ loaded, + AMOAND => rs2_val & loaded, + AMOOR => rs2_val | loaded, + + /* These operations convert bitvectors to integer values using [un]signed, + * and back using to_bits(). + */ + AMOMIN => to_bits(sizeof(xlen), min(signed(rs2_val), signed(loaded))), + AMOMAX => to_bits(sizeof(xlen), max(signed(rs2_val), signed(loaded))), + AMOMINU => to_bits(sizeof(xlen), min(unsigned(rs2_val), unsigned(loaded))), + AMOMAXU => to_bits(sizeof(xlen), max(unsigned(rs2_val), unsigned(loaded))) + }; + let rval : xlenbits = match width { + BYTE => sign_extend(loaded[7..0]), + HALF => sign_extend(loaded[15..0]), + WORD => sign_extend(loaded[31..0]), + DOUBLE => loaded + }; + let wval : MemoryOpResult(bool) = match (width, sizeof(xlen)) { + (BYTE, _) => mem_write_value(addr, 1, result[7..0], aq & rl, rl, true), + (HALF, _) => mem_write_value(addr, 2, result[15..0], aq & rl, rl, true), + (WORD, _) => mem_write_value(addr, 4, result[31..0], aq & rl, rl, true), + (DOUBLE, 64) => mem_write_value(addr, 8, result, aq & rl, rl, true), + _ => internal_error(__FILE__, __LINE__, "Unexpected AMO width") + }; + match (wval) { + MemValue(true) => { X(rd) = rval; RETIRE_SUCCESS }, + MemValue(false) => { internal_error(__FILE__, __LINE__, "AMO got false from mem_write_value") }, + MemException(e) => { handle_mem_exception(vaddr, e); RETIRE_FAIL } + } + } + } + } + } + } + } + } + } + } else { + handle_illegal(); + RETIRE_FAIL + } + } + +# SPDX-SnippetEnd diff --git a/spec/std/isa/inst/Zaamo/amominu.d.aq.yaml b/spec/std/isa/inst/Zaamo/amominu.d.aq.yaml new file mode 100644 index 0000000000..20ed5de9fc --- /dev/null +++ b/spec/std/isa/inst/Zaamo/amominu.d.aq.yaml @@ -0,0 +1,140 @@ +# Copyright (c) Qualcomm Technologies, Inc. and/or its subsidiaries. + +# WARNING: This file is auto-generated from spec/std/isa/inst/Zaamo/amominu.SIZE.AQRL.layout# Copyright (c) Abhijit Das(Sukuna0007Abhi) +# SPDX-License-Identifier: BSD-3-Clause-Clear + +# yaml-language-server: $schema=../../../../schemas/inst_schema.json + +$schema: "inst_schema.json#" +kind: instruction +name: amominu.d.aq +long_name: Atomic MIN unsigned doubleword (acquire) +description: | + Atomically with acquire ordering: + + * Load the doubleword at address _xs1_ + * Write the loaded value into _xd_ + * Unsigned compare the value of register _xs2_ to the loaded value, and select the minimum value + * Write the minimum to the address in _xs1_ +definedBy: Zaamo +base: 64 +assembly: xd, xs2, (xs1) +encoding: + match: 1100010----------011-----0101111 + variables: + - name: xs2 + location: 24-20 + - name: xs1 + location: 19-15 + - name: xd + location: 11-7 +access: + s: always + u: always + vs: always + vu: always +operation(): | + if (!implemented?(ExtensionName::A) || (MISA_CSR_IMPLEMENTED && (CSR[misa].A == 1'b0))) { + raise (ExceptionCode::IllegalInstruction, mode(), $encoding); + } + + memory_model_acquire(); + + XReg virtual_address = X[xs1]; + X[xd] = amo<64>(virtual_address, X[xs2], AmoOperation::Minu, 1'b1, 1'b0, $encoding); + +# SPDX-SnippetBegin +# SPDX-FileCopyrightText: 2017-2025 Contributors to the RISCV Sail Model +# SPDX-License-Identifier: BSD-2-Clause +sail(): | + { + if extension("A") then { + /* Get the address, X(rs1) (no offset). + * Some extensions perform additional checks on address validity. + */ + match ext_data_get_addr(rs1, zeros(), ReadWrite(Data, Data), width) { + Ext_DataAddr_Error(e) => { ext_handle_data_check_error(e); RETIRE_FAIL }, + Ext_DataAddr_OK(vaddr) => { + match translateAddr(vaddr, ReadWrite(Data, Data)) { + TR_Failure(e, _) => { handle_mem_exception(vaddr, e); RETIRE_FAIL }, + TR_Address(addr, _) => { + let eares : MemoryOpResult(unit) = match (width, sizeof(xlen)) { + (BYTE, _) => mem_write_ea(addr, 1, aq & rl, rl, true), + (HALF, _) => mem_write_ea(addr, 2, aq & rl, rl, true), + (WORD, _) => mem_write_ea(addr, 4, aq & rl, rl, true), + (DOUBLE, 64) => mem_write_ea(addr, 8, aq & rl, rl, true), + _ => internal_error(__FILE__, __LINE__, "Unexpected AMO width") + }; + let is_unsigned : bool = match op { + AMOMINU => true, + AMOMAXU => true, + _ => false + }; + let rs2_val : xlenbits = match width { + BYTE => if is_unsigned then zero_extend(X(rs2)[7..0]) else sign_extend(X(rs2)[7..0]), + HALF => if is_unsigned then zero_extend(X(rs2)[15..0]) else sign_extend(X(rs2)[15..0]), + WORD => if is_unsigned then zero_extend(X(rs2)[31..0]) else sign_extend(X(rs2)[31..0]), + DOUBLE => X(rs2) + }; + match (eares) { + MemException(e) => { handle_mem_exception(vaddr, e); RETIRE_FAIL }, + MemValue(_) => { + let mval : MemoryOpResult(xlenbits) = match (width, sizeof(xlen)) { + (BYTE, _) => extend_value(is_unsigned, mem_read(ReadWrite(Data, Data), addr, 1, aq, aq & rl, true)), + (HALF, _) => extend_value(is_unsigned, mem_read(ReadWrite(Data, Data), addr, 2, aq, aq & rl, true)), + (WORD, _) => extend_value(is_unsigned, mem_read(ReadWrite(Data, Data), addr, 4, aq, aq & rl, true)), + (DOUBLE, 64) => extend_value(is_unsigned, mem_read(ReadWrite(Data, Data), addr, 8, aq, aq & rl, true)), + _ => internal_error(__FILE__, __LINE__, "Unexpected AMO width") + }; + match (mval) { + MemException(e) => { handle_mem_exception(vaddr, e); RETIRE_FAIL }, + MemValue(loaded) => { + let result : xlenbits = + match op { + AMOSWAP => rs2_val, + AMOADD => rs2_val + loaded, + AMOXOR => rs2_val ^ loaded, + AMOAND => rs2_val & loaded, + AMOOR => rs2_val | loaded, + + /* These operations convert bitvectors to integer values using [un]signed, + * and back using to_bits(). + */ + AMOMIN => to_bits(sizeof(xlen), min(signed(rs2_val), signed(loaded))), + AMOMAX => to_bits(sizeof(xlen), max(signed(rs2_val), signed(loaded))), + AMOMINU => to_bits(sizeof(xlen), min(unsigned(rs2_val), unsigned(loaded))), + AMOMAXU => to_bits(sizeof(xlen), max(unsigned(rs2_val), unsigned(loaded))) + }; + let rval : xlenbits = match width { + BYTE => sign_extend(loaded[7..0]), + HALF => sign_extend(loaded[15..0]), + WORD => sign_extend(loaded[31..0]), + DOUBLE => loaded + }; + let wval : MemoryOpResult(bool) = match (width, sizeof(xlen)) { + (BYTE, _) => mem_write_value(addr, 1, result[7..0], aq & rl, rl, true), + (HALF, _) => mem_write_value(addr, 2, result[15..0], aq & rl, rl, true), + (WORD, _) => mem_write_value(addr, 4, result[31..0], aq & rl, rl, true), + (DOUBLE, 64) => mem_write_value(addr, 8, result, aq & rl, rl, true), + _ => internal_error(__FILE__, __LINE__, "Unexpected AMO width") + }; + match (wval) { + MemValue(true) => { X(rd) = rval; RETIRE_SUCCESS }, + MemValue(false) => { internal_error(__FILE__, __LINE__, "AMO got false from mem_write_value") }, + MemException(e) => { handle_mem_exception(vaddr, e); RETIRE_FAIL } + } + } + } + } + } + } + } + } + } + } else { + handle_illegal(); + RETIRE_FAIL + } + } + +# SPDX-SnippetEnd diff --git a/spec/std/isa/inst/Zaamo/amominu.d.aqrl.yaml b/spec/std/isa/inst/Zaamo/amominu.d.aqrl.yaml new file mode 100644 index 0000000000..e372d1f3b0 --- /dev/null +++ b/spec/std/isa/inst/Zaamo/amominu.d.aqrl.yaml @@ -0,0 +1,142 @@ +# Copyright (c) Qualcomm Technologies, Inc. and/or its subsidiaries. + +# WARNING: This file is auto-generated from spec/std/isa/inst/Zaamo/amominu.SIZE.AQRL.layout# Copyright (c) Abhijit Das(Sukuna0007Abhi) +# SPDX-License-Identifier: BSD-3-Clause-Clear + +# yaml-language-server: $schema=../../../../schemas/inst_schema.json + +$schema: "inst_schema.json#" +kind: instruction +name: amominu.d.aqrl +long_name: Atomic MIN unsigned doubleword (acquire-release) +description: | + Atomically with acquire and release ordering: + + * Load the doubleword at address _xs1_ + * Write the loaded value into _xd_ + * Unsigned compare the value of register _xs2_ to the loaded value, and select the minimum value + * Write the minimum to the address in _xs1_ +definedBy: Zaamo +base: 64 +assembly: xd, xs2, (xs1) +encoding: + match: 1100011----------011-----0101111 + variables: + - name: xs2 + location: 24-20 + - name: xs1 + location: 19-15 + - name: xd + location: 11-7 +access: + s: always + u: always + vs: always + vu: always +operation(): | + if (!implemented?(ExtensionName::A) || (MISA_CSR_IMPLEMENTED && (CSR[misa].A == 1'b0))) { + raise (ExceptionCode::IllegalInstruction, mode(), $encoding); + } + + memory_model_acquire(); + + XReg virtual_address = X[xs1]; + X[xd] = amo<64>(virtual_address, X[xs2], AmoOperation::Minu, 1'b1, 1'b1, $encoding); + + memory_model_release(); + +# SPDX-SnippetBegin +# SPDX-FileCopyrightText: 2017-2025 Contributors to the RISCV Sail Model +# SPDX-License-Identifier: BSD-2-Clause +sail(): | + { + if extension("A") then { + /* Get the address, X(rs1) (no offset). + * Some extensions perform additional checks on address validity. + */ + match ext_data_get_addr(rs1, zeros(), ReadWrite(Data, Data), width) { + Ext_DataAddr_Error(e) => { ext_handle_data_check_error(e); RETIRE_FAIL }, + Ext_DataAddr_OK(vaddr) => { + match translateAddr(vaddr, ReadWrite(Data, Data)) { + TR_Failure(e, _) => { handle_mem_exception(vaddr, e); RETIRE_FAIL }, + TR_Address(addr, _) => { + let eares : MemoryOpResult(unit) = match (width, sizeof(xlen)) { + (BYTE, _) => mem_write_ea(addr, 1, aq & rl, rl, true), + (HALF, _) => mem_write_ea(addr, 2, aq & rl, rl, true), + (WORD, _) => mem_write_ea(addr, 4, aq & rl, rl, true), + (DOUBLE, 64) => mem_write_ea(addr, 8, aq & rl, rl, true), + _ => internal_error(__FILE__, __LINE__, "Unexpected AMO width") + }; + let is_unsigned : bool = match op { + AMOMINU => true, + AMOMAXU => true, + _ => false + }; + let rs2_val : xlenbits = match width { + BYTE => if is_unsigned then zero_extend(X(rs2)[7..0]) else sign_extend(X(rs2)[7..0]), + HALF => if is_unsigned then zero_extend(X(rs2)[15..0]) else sign_extend(X(rs2)[15..0]), + WORD => if is_unsigned then zero_extend(X(rs2)[31..0]) else sign_extend(X(rs2)[31..0]), + DOUBLE => X(rs2) + }; + match (eares) { + MemException(e) => { handle_mem_exception(vaddr, e); RETIRE_FAIL }, + MemValue(_) => { + let mval : MemoryOpResult(xlenbits) = match (width, sizeof(xlen)) { + (BYTE, _) => extend_value(is_unsigned, mem_read(ReadWrite(Data, Data), addr, 1, aq, aq & rl, true)), + (HALF, _) => extend_value(is_unsigned, mem_read(ReadWrite(Data, Data), addr, 2, aq, aq & rl, true)), + (WORD, _) => extend_value(is_unsigned, mem_read(ReadWrite(Data, Data), addr, 4, aq, aq & rl, true)), + (DOUBLE, 64) => extend_value(is_unsigned, mem_read(ReadWrite(Data, Data), addr, 8, aq, aq & rl, true)), + _ => internal_error(__FILE__, __LINE__, "Unexpected AMO width") + }; + match (mval) { + MemException(e) => { handle_mem_exception(vaddr, e); RETIRE_FAIL }, + MemValue(loaded) => { + let result : xlenbits = + match op { + AMOSWAP => rs2_val, + AMOADD => rs2_val + loaded, + AMOXOR => rs2_val ^ loaded, + AMOAND => rs2_val & loaded, + AMOOR => rs2_val | loaded, + + /* These operations convert bitvectors to integer values using [un]signed, + * and back using to_bits(). + */ + AMOMIN => to_bits(sizeof(xlen), min(signed(rs2_val), signed(loaded))), + AMOMAX => to_bits(sizeof(xlen), max(signed(rs2_val), signed(loaded))), + AMOMINU => to_bits(sizeof(xlen), min(unsigned(rs2_val), unsigned(loaded))), + AMOMAXU => to_bits(sizeof(xlen), max(unsigned(rs2_val), unsigned(loaded))) + }; + let rval : xlenbits = match width { + BYTE => sign_extend(loaded[7..0]), + HALF => sign_extend(loaded[15..0]), + WORD => sign_extend(loaded[31..0]), + DOUBLE => loaded + }; + let wval : MemoryOpResult(bool) = match (width, sizeof(xlen)) { + (BYTE, _) => mem_write_value(addr, 1, result[7..0], aq & rl, rl, true), + (HALF, _) => mem_write_value(addr, 2, result[15..0], aq & rl, rl, true), + (WORD, _) => mem_write_value(addr, 4, result[31..0], aq & rl, rl, true), + (DOUBLE, 64) => mem_write_value(addr, 8, result, aq & rl, rl, true), + _ => internal_error(__FILE__, __LINE__, "Unexpected AMO width") + }; + match (wval) { + MemValue(true) => { X(rd) = rval; RETIRE_SUCCESS }, + MemValue(false) => { internal_error(__FILE__, __LINE__, "AMO got false from mem_write_value") }, + MemException(e) => { handle_mem_exception(vaddr, e); RETIRE_FAIL } + } + } + } + } + } + } + } + } + } + } else { + handle_illegal(); + RETIRE_FAIL + } + } + +# SPDX-SnippetEnd diff --git a/spec/std/isa/inst/Zaamo/amominu.d.rl.yaml b/spec/std/isa/inst/Zaamo/amominu.d.rl.yaml new file mode 100644 index 0000000000..fa46d3a17b --- /dev/null +++ b/spec/std/isa/inst/Zaamo/amominu.d.rl.yaml @@ -0,0 +1,140 @@ +# Copyright (c) Qualcomm Technologies, Inc. and/or its subsidiaries. + +# WARNING: This file is auto-generated from spec/std/isa/inst/Zaamo/amominu.SIZE.AQRL.layout# Copyright (c) Abhijit Das(Sukuna0007Abhi) +# SPDX-License-Identifier: BSD-3-Clause-Clear + +# yaml-language-server: $schema=../../../../schemas/inst_schema.json + +$schema: "inst_schema.json#" +kind: instruction +name: amominu.d.rl +long_name: Atomic MIN unsigned doubleword (release) +description: | + Atomically with release ordering: + + * Load the doubleword at address _xs1_ + * Write the loaded value into _xd_ + * Unsigned compare the value of register _xs2_ to the loaded value, and select the minimum value + * Write the minimum to the address in _xs1_ +definedBy: Zaamo +base: 64 +assembly: xd, xs2, (xs1) +encoding: + match: 1100001----------011-----0101111 + variables: + - name: xs2 + location: 24-20 + - name: xs1 + location: 19-15 + - name: xd + location: 11-7 +access: + s: always + u: always + vs: always + vu: always +operation(): | + if (!implemented?(ExtensionName::A) || (MISA_CSR_IMPLEMENTED && (CSR[misa].A == 1'b0))) { + raise (ExceptionCode::IllegalInstruction, mode(), $encoding); + } + + XReg virtual_address = X[xs1]; + X[xd] = amo<64>(virtual_address, X[xs2], AmoOperation::Minu, 1'b0, 1'b1, $encoding); + + memory_model_release(); + +# SPDX-SnippetBegin +# SPDX-FileCopyrightText: 2017-2025 Contributors to the RISCV Sail Model +# SPDX-License-Identifier: BSD-2-Clause +sail(): | + { + if extension("A") then { + /* Get the address, X(rs1) (no offset). + * Some extensions perform additional checks on address validity. + */ + match ext_data_get_addr(rs1, zeros(), ReadWrite(Data, Data), width) { + Ext_DataAddr_Error(e) => { ext_handle_data_check_error(e); RETIRE_FAIL }, + Ext_DataAddr_OK(vaddr) => { + match translateAddr(vaddr, ReadWrite(Data, Data)) { + TR_Failure(e, _) => { handle_mem_exception(vaddr, e); RETIRE_FAIL }, + TR_Address(addr, _) => { + let eares : MemoryOpResult(unit) = match (width, sizeof(xlen)) { + (BYTE, _) => mem_write_ea(addr, 1, aq & rl, rl, true), + (HALF, _) => mem_write_ea(addr, 2, aq & rl, rl, true), + (WORD, _) => mem_write_ea(addr, 4, aq & rl, rl, true), + (DOUBLE, 64) => mem_write_ea(addr, 8, aq & rl, rl, true), + _ => internal_error(__FILE__, __LINE__, "Unexpected AMO width") + }; + let is_unsigned : bool = match op { + AMOMINU => true, + AMOMAXU => true, + _ => false + }; + let rs2_val : xlenbits = match width { + BYTE => if is_unsigned then zero_extend(X(rs2)[7..0]) else sign_extend(X(rs2)[7..0]), + HALF => if is_unsigned then zero_extend(X(rs2)[15..0]) else sign_extend(X(rs2)[15..0]), + WORD => if is_unsigned then zero_extend(X(rs2)[31..0]) else sign_extend(X(rs2)[31..0]), + DOUBLE => X(rs2) + }; + match (eares) { + MemException(e) => { handle_mem_exception(vaddr, e); RETIRE_FAIL }, + MemValue(_) => { + let mval : MemoryOpResult(xlenbits) = match (width, sizeof(xlen)) { + (BYTE, _) => extend_value(is_unsigned, mem_read(ReadWrite(Data, Data), addr, 1, aq, aq & rl, true)), + (HALF, _) => extend_value(is_unsigned, mem_read(ReadWrite(Data, Data), addr, 2, aq, aq & rl, true)), + (WORD, _) => extend_value(is_unsigned, mem_read(ReadWrite(Data, Data), addr, 4, aq, aq & rl, true)), + (DOUBLE, 64) => extend_value(is_unsigned, mem_read(ReadWrite(Data, Data), addr, 8, aq, aq & rl, true)), + _ => internal_error(__FILE__, __LINE__, "Unexpected AMO width") + }; + match (mval) { + MemException(e) => { handle_mem_exception(vaddr, e); RETIRE_FAIL }, + MemValue(loaded) => { + let result : xlenbits = + match op { + AMOSWAP => rs2_val, + AMOADD => rs2_val + loaded, + AMOXOR => rs2_val ^ loaded, + AMOAND => rs2_val & loaded, + AMOOR => rs2_val | loaded, + + /* These operations convert bitvectors to integer values using [un]signed, + * and back using to_bits(). + */ + AMOMIN => to_bits(sizeof(xlen), min(signed(rs2_val), signed(loaded))), + AMOMAX => to_bits(sizeof(xlen), max(signed(rs2_val), signed(loaded))), + AMOMINU => to_bits(sizeof(xlen), min(unsigned(rs2_val), unsigned(loaded))), + AMOMAXU => to_bits(sizeof(xlen), max(unsigned(rs2_val), unsigned(loaded))) + }; + let rval : xlenbits = match width { + BYTE => sign_extend(loaded[7..0]), + HALF => sign_extend(loaded[15..0]), + WORD => sign_extend(loaded[31..0]), + DOUBLE => loaded + }; + let wval : MemoryOpResult(bool) = match (width, sizeof(xlen)) { + (BYTE, _) => mem_write_value(addr, 1, result[7..0], aq & rl, rl, true), + (HALF, _) => mem_write_value(addr, 2, result[15..0], aq & rl, rl, true), + (WORD, _) => mem_write_value(addr, 4, result[31..0], aq & rl, rl, true), + (DOUBLE, 64) => mem_write_value(addr, 8, result, aq & rl, rl, true), + _ => internal_error(__FILE__, __LINE__, "Unexpected AMO width") + }; + match (wval) { + MemValue(true) => { X(rd) = rval; RETIRE_SUCCESS }, + MemValue(false) => { internal_error(__FILE__, __LINE__, "AMO got false from mem_write_value") }, + MemException(e) => { handle_mem_exception(vaddr, e); RETIRE_FAIL } + } + } + } + } + } + } + } + } + } + } else { + handle_illegal(); + RETIRE_FAIL + } + } + +# SPDX-SnippetEnd diff --git a/spec/std/isa/inst/Zaamo/amominu.d.yaml b/spec/std/isa/inst/Zaamo/amominu.d.yaml index d3446b2690..5fd76a1dde 100644 --- a/spec/std/isa/inst/Zaamo/amominu.d.yaml +++ b/spec/std/isa/inst/Zaamo/amominu.d.yaml @@ -1,4 +1,6 @@ # Copyright (c) Qualcomm Technologies, Inc. and/or its subsidiaries. + +# WARNING: This file is auto-generated from spec/std/isa/inst/Zaamo/amominu.SIZE.AQRL.layout# Copyright (c) Abhijit Das(Sukuna0007Abhi) # SPDX-License-Identifier: BSD-3-Clause-Clear # yaml-language-server: $schema=../../../../schemas/inst_schema.json @@ -18,12 +20,8 @@ definedBy: Zaamo base: 64 assembly: xd, xs2, (xs1) encoding: - match: 11000------------011-----0101111 + match: 1100000----------011-----0101111 variables: - - name: aq - location: 26 - - name: rl - location: 25 - name: xs2 location: 24-20 - name: xs1 @@ -36,15 +34,12 @@ access: vs: always vu: always operation(): | - if (implemented?(ExtensionName::A) && (CSR[misa].A == 1'b0)) { - # even though this is a memory operation, the exception occurs before that would be known, - # so mode() is the correct reporting mode rathat than effective_ldst_mode() + if (!implemented?(ExtensionName::A) || (MISA_CSR_IMPLEMENTED && (CSR[misa].A == 1'b0))) { raise (ExceptionCode::IllegalInstruction, mode(), $encoding); } XReg virtual_address = X[xs1]; - - X[xd] = amo<64>(virtual_address, X[xs2], AmoOperation::Minu, aq, rl, $encoding); + X[xd] = amo<64>(virtual_address, X[xs2], AmoOperation::Minu, 1'b0, 1'b0, $encoding); # SPDX-SnippetBegin # SPDX-FileCopyrightText: 2017-2025 Contributors to the RISCV Sail Model diff --git a/spec/std/isa/inst/Zaamo/amominu.w.aq.yaml b/spec/std/isa/inst/Zaamo/amominu.w.aq.yaml new file mode 100644 index 0000000000..5a0dfa5ecc --- /dev/null +++ b/spec/std/isa/inst/Zaamo/amominu.w.aq.yaml @@ -0,0 +1,139 @@ +# Copyright (c) Qualcomm Technologies, Inc. and/or its subsidiaries. + +# WARNING: This file is auto-generated from spec/std/isa/inst/Zaamo/amominu.SIZE.AQRL.layout# Copyright (c) Abhijit Das(Sukuna0007Abhi) +# SPDX-License-Identifier: BSD-3-Clause-Clear + +# yaml-language-server: $schema=../../../../schemas/inst_schema.json + +$schema: "inst_schema.json#" +kind: instruction +name: amominu.w.aq +long_name: Atomic MIN unsigned word (acquire) +description: | + Atomically with acquire ordering: + + * Load the word at address _xs1_ + * Write the sign-extended value into _xd_ + * Unsigned compare the least-significant word of register _xs2_ to the loaded value, and select the minimum value + * Write the minimum to the address in _xs1_ +definedBy: Zaamo +assembly: xd, xs2, (xs1) +encoding: + match: 1100010----------010-----0101111 + variables: + - name: xs2 + location: 24-20 + - name: xs1 + location: 19-15 + - name: xd + location: 11-7 +access: + s: always + u: always + vs: always + vu: always +operation(): | + if (!implemented?(ExtensionName::A) || (MISA_CSR_IMPLEMENTED && (CSR[misa].A == 1'b0))) { + raise (ExceptionCode::IllegalInstruction, mode(), $encoding); + } + + memory_model_acquire(); + + XReg virtual_address = X[xs1]; + X[xd] = amo<32>(virtual_address, X[xs2][31:0], AmoOperation::Minu, 1'b1, 1'b0, $encoding); + +# SPDX-SnippetBegin +# SPDX-FileCopyrightText: 2017-2025 Contributors to the RISCV Sail Model +# SPDX-License-Identifier: BSD-2-Clause +sail(): | + { + if extension("A") then { + /* Get the address, X(rs1) (no offset). + * Some extensions perform additional checks on address validity. + */ + match ext_data_get_addr(rs1, zeros(), ReadWrite(Data, Data), width) { + Ext_DataAddr_Error(e) => { ext_handle_data_check_error(e); RETIRE_FAIL }, + Ext_DataAddr_OK(vaddr) => { + match translateAddr(vaddr, ReadWrite(Data, Data)) { + TR_Failure(e, _) => { handle_mem_exception(vaddr, e); RETIRE_FAIL }, + TR_Address(addr, _) => { + let eares : MemoryOpResult(unit) = match (width, sizeof(xlen)) { + (BYTE, _) => mem_write_ea(addr, 1, aq & rl, rl, true), + (HALF, _) => mem_write_ea(addr, 2, aq & rl, rl, true), + (WORD, _) => mem_write_ea(addr, 4, aq & rl, rl, true), + (DOUBLE, 64) => mem_write_ea(addr, 8, aq & rl, rl, true), + _ => internal_error(__FILE__, __LINE__, "Unexpected AMO width") + }; + let is_unsigned : bool = match op { + AMOMINU => true, + AMOMAXU => true, + _ => false + }; + let rs2_val : xlenbits = match width { + BYTE => if is_unsigned then zero_extend(X(rs2)[7..0]) else sign_extend(X(rs2)[7..0]), + HALF => if is_unsigned then zero_extend(X(rs2)[15..0]) else sign_extend(X(rs2)[15..0]), + WORD => if is_unsigned then zero_extend(X(rs2)[31..0]) else sign_extend(X(rs2)[31..0]), + DOUBLE => X(rs2) + }; + match (eares) { + MemException(e) => { handle_mem_exception(vaddr, e); RETIRE_FAIL }, + MemValue(_) => { + let mval : MemoryOpResult(xlenbits) = match (width, sizeof(xlen)) { + (BYTE, _) => extend_value(is_unsigned, mem_read(ReadWrite(Data, Data), addr, 1, aq, aq & rl, true)), + (HALF, _) => extend_value(is_unsigned, mem_read(ReadWrite(Data, Data), addr, 2, aq, aq & rl, true)), + (WORD, _) => extend_value(is_unsigned, mem_read(ReadWrite(Data, Data), addr, 4, aq, aq & rl, true)), + (DOUBLE, 64) => extend_value(is_unsigned, mem_read(ReadWrite(Data, Data), addr, 8, aq, aq & rl, true)), + _ => internal_error(__FILE__, __LINE__, "Unexpected AMO width") + }; + match (mval) { + MemException(e) => { handle_mem_exception(vaddr, e); RETIRE_FAIL }, + MemValue(loaded) => { + let result : xlenbits = + match op { + AMOSWAP => rs2_val, + AMOADD => rs2_val + loaded, + AMOXOR => rs2_val ^ loaded, + AMOAND => rs2_val & loaded, + AMOOR => rs2_val | loaded, + + /* These operations convert bitvectors to integer values using [un]signed, + * and back using to_bits(). + */ + AMOMIN => to_bits(sizeof(xlen), min(signed(rs2_val), signed(loaded))), + AMOMAX => to_bits(sizeof(xlen), max(signed(rs2_val), signed(loaded))), + AMOMINU => to_bits(sizeof(xlen), min(unsigned(rs2_val), unsigned(loaded))), + AMOMAXU => to_bits(sizeof(xlen), max(unsigned(rs2_val), unsigned(loaded))) + }; + let rval : xlenbits = match width { + BYTE => sign_extend(loaded[7..0]), + HALF => sign_extend(loaded[15..0]), + WORD => sign_extend(loaded[31..0]), + DOUBLE => loaded + }; + let wval : MemoryOpResult(bool) = match (width, sizeof(xlen)) { + (BYTE, _) => mem_write_value(addr, 1, result[7..0], aq & rl, rl, true), + (HALF, _) => mem_write_value(addr, 2, result[15..0], aq & rl, rl, true), + (WORD, _) => mem_write_value(addr, 4, result[31..0], aq & rl, rl, true), + (DOUBLE, 64) => mem_write_value(addr, 8, result, aq & rl, rl, true), + _ => internal_error(__FILE__, __LINE__, "Unexpected AMO width") + }; + match (wval) { + MemValue(true) => { X(rd) = rval; RETIRE_SUCCESS }, + MemValue(false) => { internal_error(__FILE__, __LINE__, "AMO got false from mem_write_value") }, + MemException(e) => { handle_mem_exception(vaddr, e); RETIRE_FAIL } + } + } + } + } + } + } + } + } + } + } else { + handle_illegal(); + RETIRE_FAIL + } + } + +# SPDX-SnippetEnd diff --git a/spec/std/isa/inst/Zaamo/amominu.w.aqrl.yaml b/spec/std/isa/inst/Zaamo/amominu.w.aqrl.yaml new file mode 100644 index 0000000000..81cdc9d876 --- /dev/null +++ b/spec/std/isa/inst/Zaamo/amominu.w.aqrl.yaml @@ -0,0 +1,141 @@ +# Copyright (c) Qualcomm Technologies, Inc. and/or its subsidiaries. + +# WARNING: This file is auto-generated from spec/std/isa/inst/Zaamo/amominu.SIZE.AQRL.layout# Copyright (c) Abhijit Das(Sukuna0007Abhi) +# SPDX-License-Identifier: BSD-3-Clause-Clear + +# yaml-language-server: $schema=../../../../schemas/inst_schema.json + +$schema: "inst_schema.json#" +kind: instruction +name: amominu.w.aqrl +long_name: Atomic MIN unsigned word (acquire-release) +description: | + Atomically with acquire and release ordering: + + * Load the word at address _xs1_ + * Write the sign-extended value into _xd_ + * Unsigned compare the least-significant word of register _xs2_ to the loaded value, and select the minimum value + * Write the minimum to the address in _xs1_ +definedBy: Zaamo +assembly: xd, xs2, (xs1) +encoding: + match: 1100011----------010-----0101111 + variables: + - name: xs2 + location: 24-20 + - name: xs1 + location: 19-15 + - name: xd + location: 11-7 +access: + s: always + u: always + vs: always + vu: always +operation(): | + if (!implemented?(ExtensionName::A) || (MISA_CSR_IMPLEMENTED && (CSR[misa].A == 1'b0))) { + raise (ExceptionCode::IllegalInstruction, mode(), $encoding); + } + + memory_model_acquire(); + + XReg virtual_address = X[xs1]; + X[xd] = amo<32>(virtual_address, X[xs2][31:0], AmoOperation::Minu, 1'b1, 1'b1, $encoding); + + memory_model_release(); + +# SPDX-SnippetBegin +# SPDX-FileCopyrightText: 2017-2025 Contributors to the RISCV Sail Model +# SPDX-License-Identifier: BSD-2-Clause +sail(): | + { + if extension("A") then { + /* Get the address, X(rs1) (no offset). + * Some extensions perform additional checks on address validity. + */ + match ext_data_get_addr(rs1, zeros(), ReadWrite(Data, Data), width) { + Ext_DataAddr_Error(e) => { ext_handle_data_check_error(e); RETIRE_FAIL }, + Ext_DataAddr_OK(vaddr) => { + match translateAddr(vaddr, ReadWrite(Data, Data)) { + TR_Failure(e, _) => { handle_mem_exception(vaddr, e); RETIRE_FAIL }, + TR_Address(addr, _) => { + let eares : MemoryOpResult(unit) = match (width, sizeof(xlen)) { + (BYTE, _) => mem_write_ea(addr, 1, aq & rl, rl, true), + (HALF, _) => mem_write_ea(addr, 2, aq & rl, rl, true), + (WORD, _) => mem_write_ea(addr, 4, aq & rl, rl, true), + (DOUBLE, 64) => mem_write_ea(addr, 8, aq & rl, rl, true), + _ => internal_error(__FILE__, __LINE__, "Unexpected AMO width") + }; + let is_unsigned : bool = match op { + AMOMINU => true, + AMOMAXU => true, + _ => false + }; + let rs2_val : xlenbits = match width { + BYTE => if is_unsigned then zero_extend(X(rs2)[7..0]) else sign_extend(X(rs2)[7..0]), + HALF => if is_unsigned then zero_extend(X(rs2)[15..0]) else sign_extend(X(rs2)[15..0]), + WORD => if is_unsigned then zero_extend(X(rs2)[31..0]) else sign_extend(X(rs2)[31..0]), + DOUBLE => X(rs2) + }; + match (eares) { + MemException(e) => { handle_mem_exception(vaddr, e); RETIRE_FAIL }, + MemValue(_) => { + let mval : MemoryOpResult(xlenbits) = match (width, sizeof(xlen)) { + (BYTE, _) => extend_value(is_unsigned, mem_read(ReadWrite(Data, Data), addr, 1, aq, aq & rl, true)), + (HALF, _) => extend_value(is_unsigned, mem_read(ReadWrite(Data, Data), addr, 2, aq, aq & rl, true)), + (WORD, _) => extend_value(is_unsigned, mem_read(ReadWrite(Data, Data), addr, 4, aq, aq & rl, true)), + (DOUBLE, 64) => extend_value(is_unsigned, mem_read(ReadWrite(Data, Data), addr, 8, aq, aq & rl, true)), + _ => internal_error(__FILE__, __LINE__, "Unexpected AMO width") + }; + match (mval) { + MemException(e) => { handle_mem_exception(vaddr, e); RETIRE_FAIL }, + MemValue(loaded) => { + let result : xlenbits = + match op { + AMOSWAP => rs2_val, + AMOADD => rs2_val + loaded, + AMOXOR => rs2_val ^ loaded, + AMOAND => rs2_val & loaded, + AMOOR => rs2_val | loaded, + + /* These operations convert bitvectors to integer values using [un]signed, + * and back using to_bits(). + */ + AMOMIN => to_bits(sizeof(xlen), min(signed(rs2_val), signed(loaded))), + AMOMAX => to_bits(sizeof(xlen), max(signed(rs2_val), signed(loaded))), + AMOMINU => to_bits(sizeof(xlen), min(unsigned(rs2_val), unsigned(loaded))), + AMOMAXU => to_bits(sizeof(xlen), max(unsigned(rs2_val), unsigned(loaded))) + }; + let rval : xlenbits = match width { + BYTE => sign_extend(loaded[7..0]), + HALF => sign_extend(loaded[15..0]), + WORD => sign_extend(loaded[31..0]), + DOUBLE => loaded + }; + let wval : MemoryOpResult(bool) = match (width, sizeof(xlen)) { + (BYTE, _) => mem_write_value(addr, 1, result[7..0], aq & rl, rl, true), + (HALF, _) => mem_write_value(addr, 2, result[15..0], aq & rl, rl, true), + (WORD, _) => mem_write_value(addr, 4, result[31..0], aq & rl, rl, true), + (DOUBLE, 64) => mem_write_value(addr, 8, result, aq & rl, rl, true), + _ => internal_error(__FILE__, __LINE__, "Unexpected AMO width") + }; + match (wval) { + MemValue(true) => { X(rd) = rval; RETIRE_SUCCESS }, + MemValue(false) => { internal_error(__FILE__, __LINE__, "AMO got false from mem_write_value") }, + MemException(e) => { handle_mem_exception(vaddr, e); RETIRE_FAIL } + } + } + } + } + } + } + } + } + } + } else { + handle_illegal(); + RETIRE_FAIL + } + } + +# SPDX-SnippetEnd diff --git a/spec/std/isa/inst/Zaamo/amominu.w.rl.yaml b/spec/std/isa/inst/Zaamo/amominu.w.rl.yaml new file mode 100644 index 0000000000..0bdaee9ee2 --- /dev/null +++ b/spec/std/isa/inst/Zaamo/amominu.w.rl.yaml @@ -0,0 +1,139 @@ +# Copyright (c) Qualcomm Technologies, Inc. and/or its subsidiaries. + +# WARNING: This file is auto-generated from spec/std/isa/inst/Zaamo/amominu.SIZE.AQRL.layout# Copyright (c) Abhijit Das(Sukuna0007Abhi) +# SPDX-License-Identifier: BSD-3-Clause-Clear + +# yaml-language-server: $schema=../../../../schemas/inst_schema.json + +$schema: "inst_schema.json#" +kind: instruction +name: amominu.w.rl +long_name: Atomic MIN unsigned word (release) +description: | + Atomically with release ordering: + + * Load the word at address _xs1_ + * Write the sign-extended value into _xd_ + * Unsigned compare the least-significant word of register _xs2_ to the loaded value, and select the minimum value + * Write the minimum to the address in _xs1_ +definedBy: Zaamo +assembly: xd, xs2, (xs1) +encoding: + match: 1100001----------010-----0101111 + variables: + - name: xs2 + location: 24-20 + - name: xs1 + location: 19-15 + - name: xd + location: 11-7 +access: + s: always + u: always + vs: always + vu: always +operation(): | + if (!implemented?(ExtensionName::A) || (MISA_CSR_IMPLEMENTED && (CSR[misa].A == 1'b0))) { + raise (ExceptionCode::IllegalInstruction, mode(), $encoding); + } + + XReg virtual_address = X[xs1]; + X[xd] = amo<32>(virtual_address, X[xs2][31:0], AmoOperation::Minu, 1'b0, 1'b1, $encoding); + + memory_model_release(); + +# SPDX-SnippetBegin +# SPDX-FileCopyrightText: 2017-2025 Contributors to the RISCV Sail Model +# SPDX-License-Identifier: BSD-2-Clause +sail(): | + { + if extension("A") then { + /* Get the address, X(rs1) (no offset). + * Some extensions perform additional checks on address validity. + */ + match ext_data_get_addr(rs1, zeros(), ReadWrite(Data, Data), width) { + Ext_DataAddr_Error(e) => { ext_handle_data_check_error(e); RETIRE_FAIL }, + Ext_DataAddr_OK(vaddr) => { + match translateAddr(vaddr, ReadWrite(Data, Data)) { + TR_Failure(e, _) => { handle_mem_exception(vaddr, e); RETIRE_FAIL }, + TR_Address(addr, _) => { + let eares : MemoryOpResult(unit) = match (width, sizeof(xlen)) { + (BYTE, _) => mem_write_ea(addr, 1, aq & rl, rl, true), + (HALF, _) => mem_write_ea(addr, 2, aq & rl, rl, true), + (WORD, _) => mem_write_ea(addr, 4, aq & rl, rl, true), + (DOUBLE, 64) => mem_write_ea(addr, 8, aq & rl, rl, true), + _ => internal_error(__FILE__, __LINE__, "Unexpected AMO width") + }; + let is_unsigned : bool = match op { + AMOMINU => true, + AMOMAXU => true, + _ => false + }; + let rs2_val : xlenbits = match width { + BYTE => if is_unsigned then zero_extend(X(rs2)[7..0]) else sign_extend(X(rs2)[7..0]), + HALF => if is_unsigned then zero_extend(X(rs2)[15..0]) else sign_extend(X(rs2)[15..0]), + WORD => if is_unsigned then zero_extend(X(rs2)[31..0]) else sign_extend(X(rs2)[31..0]), + DOUBLE => X(rs2) + }; + match (eares) { + MemException(e) => { handle_mem_exception(vaddr, e); RETIRE_FAIL }, + MemValue(_) => { + let mval : MemoryOpResult(xlenbits) = match (width, sizeof(xlen)) { + (BYTE, _) => extend_value(is_unsigned, mem_read(ReadWrite(Data, Data), addr, 1, aq, aq & rl, true)), + (HALF, _) => extend_value(is_unsigned, mem_read(ReadWrite(Data, Data), addr, 2, aq, aq & rl, true)), + (WORD, _) => extend_value(is_unsigned, mem_read(ReadWrite(Data, Data), addr, 4, aq, aq & rl, true)), + (DOUBLE, 64) => extend_value(is_unsigned, mem_read(ReadWrite(Data, Data), addr, 8, aq, aq & rl, true)), + _ => internal_error(__FILE__, __LINE__, "Unexpected AMO width") + }; + match (mval) { + MemException(e) => { handle_mem_exception(vaddr, e); RETIRE_FAIL }, + MemValue(loaded) => { + let result : xlenbits = + match op { + AMOSWAP => rs2_val, + AMOADD => rs2_val + loaded, + AMOXOR => rs2_val ^ loaded, + AMOAND => rs2_val & loaded, + AMOOR => rs2_val | loaded, + + /* These operations convert bitvectors to integer values using [un]signed, + * and back using to_bits(). + */ + AMOMIN => to_bits(sizeof(xlen), min(signed(rs2_val), signed(loaded))), + AMOMAX => to_bits(sizeof(xlen), max(signed(rs2_val), signed(loaded))), + AMOMINU => to_bits(sizeof(xlen), min(unsigned(rs2_val), unsigned(loaded))), + AMOMAXU => to_bits(sizeof(xlen), max(unsigned(rs2_val), unsigned(loaded))) + }; + let rval : xlenbits = match width { + BYTE => sign_extend(loaded[7..0]), + HALF => sign_extend(loaded[15..0]), + WORD => sign_extend(loaded[31..0]), + DOUBLE => loaded + }; + let wval : MemoryOpResult(bool) = match (width, sizeof(xlen)) { + (BYTE, _) => mem_write_value(addr, 1, result[7..0], aq & rl, rl, true), + (HALF, _) => mem_write_value(addr, 2, result[15..0], aq & rl, rl, true), + (WORD, _) => mem_write_value(addr, 4, result[31..0], aq & rl, rl, true), + (DOUBLE, 64) => mem_write_value(addr, 8, result, aq & rl, rl, true), + _ => internal_error(__FILE__, __LINE__, "Unexpected AMO width") + }; + match (wval) { + MemValue(true) => { X(rd) = rval; RETIRE_SUCCESS }, + MemValue(false) => { internal_error(__FILE__, __LINE__, "AMO got false from mem_write_value") }, + MemException(e) => { handle_mem_exception(vaddr, e); RETIRE_FAIL } + } + } + } + } + } + } + } + } + } + } else { + handle_illegal(); + RETIRE_FAIL + } + } + +# SPDX-SnippetEnd diff --git a/spec/std/isa/inst/Zaamo/amominu.w.yaml b/spec/std/isa/inst/Zaamo/amominu.w.yaml index 48a8d088ea..9e8569455e 100644 --- a/spec/std/isa/inst/Zaamo/amominu.w.yaml +++ b/spec/std/isa/inst/Zaamo/amominu.w.yaml @@ -1,4 +1,6 @@ # Copyright (c) Qualcomm Technologies, Inc. and/or its subsidiaries. + +# WARNING: This file is auto-generated from spec/std/isa/inst/Zaamo/amominu.SIZE.AQRL.layout# Copyright (c) Abhijit Das(Sukuna0007Abhi) # SPDX-License-Identifier: BSD-3-Clause-Clear # yaml-language-server: $schema=../../../../schemas/inst_schema.json @@ -12,17 +14,13 @@ description: | * Load the word at address _xs1_ * Write the sign-extended value into _xd_ - * Unsigned compare the least-significant word of register _xs2_ to the loaded word, and select the minimum value - * Write the result to the address in _xs1_ + * Unsigned compare the least-significant word of register _xs2_ to the loaded value, and select the minimum value + * Write the minimum to the address in _xs1_ definedBy: Zaamo assembly: xd, xs2, (xs1) encoding: - match: 11000------------010-----0101111 + match: 1100000----------010-----0101111 variables: - - name: aq - location: 26 - - name: rl - location: 25 - name: xs2 location: 24-20 - name: xs1 @@ -35,15 +33,12 @@ access: vs: always vu: always operation(): | - if (implemented?(ExtensionName::A) && (CSR[misa].A == 1'b0)) { - # even though this is a memory operation, the exception occurs before that would be known, - # so mode() is the correct reporting mode rathat than effective_ldst_mode() + if (!implemented?(ExtensionName::A) || (MISA_CSR_IMPLEMENTED && (CSR[misa].A == 1'b0))) { raise (ExceptionCode::IllegalInstruction, mode(), $encoding); } XReg virtual_address = X[xs1]; - - X[xd] = amo<32>(virtual_address, X[xs2][31:0], AmoOperation::Minu, aq, rl, $encoding); + X[xd] = amo<32>(virtual_address, X[xs2][31:0], AmoOperation::Minu, 1'b0, 1'b0, $encoding); # SPDX-SnippetBegin # SPDX-FileCopyrightText: 2017-2025 Contributors to the RISCV Sail Model diff --git a/spec/std/isa/inst/Zaamo/amoor.SIZE.AQRL.layout b/spec/std/isa/inst/Zaamo/amoor.SIZE.AQRL.layout new file mode 100644 index 0000000000..800c29f60b --- /dev/null +++ b/spec/std/isa/inst/Zaamo/amoor.SIZE.AQRL.layout @@ -0,0 +1,175 @@ +# Copyright (c) Qualcomm Technologies, Inc. and/or its subsidiaries. +# Copyright (c) Abhijit Das(Sukuna0007Abhi) +# SPDX-License-Identifier: BSD-3-Clause-Clear + +# yaml-language-server: $schema=../../../../schemas/inst_schema.json +<%- + raise "'size' must be defined as 'b', 'h', 'w', or 'd'" unless %w[b h w d].include?(size) + raise "'aq' must be defined as true or false" unless [true, false].include?(aq) + raise "'rl' must be defined as true or false" unless [true, false].include?(rl) + + size_info = { + "b" => { name: "byte", bits: 8, funct3: "000", operation_bits: "8" }, + "h" => { name: "halfword", bits: 16, funct3: "001", operation_bits: "16" }, + "w" => { name: "word", bits: 32, funct3: "010", operation_bits: "32" }, + "d" => { name: "doubleword", bits: 64, funct3: "011", operation_bits: "64" } + } + + current_size = size_info[size] + + # Generate instruction name suffix based on aq/rl + aq_rl_suffix = "" + if aq && rl + aq_rl_suffix = ".aqrl" + elsif aq + aq_rl_suffix = ".aq" + elsif rl + aq_rl_suffix = ".rl" + end + + # Generate match string with fixed aq/rl bits + aq_bit = aq ? "1" : "0" + rl_bit = rl ? "1" : "0" +-%> + +$schema: "inst_schema.json#" +kind: instruction +name: amoor.<%= size %><%= aq_rl_suffix %> +long_name: Atomic fetch-and-or <%= current_size[:name] %><%= aq && rl ? " (acquire-release)" : (aq ? " (acquire)" : (rl ? " (release)" : "")) %> +description: | + Atomically<%= aq && rl ? " with acquire and release ordering" : (aq ? " with acquire ordering" : (rl ? " with release ordering" : "")) %>: + + * Load the <%= current_size[:name] %> at address _xs1_ + * Write the <%= %w[b h w].include?(size) ? "sign-extended value" : "loaded value" %> into _xd_ + * OR the <%= %w[b h w].include?(size) ? "least-significant #{current_size[:name]} of register" : "value of register" %> _xs2_ to the loaded value + * Write the result to the address in _xs1_ +definedBy: <%= %w[b h].include?(size) ? "Zabha" : "Zaamo" %> +<%- if size == "d" -%> +base: 64 +<%- end -%> +assembly: xd, xs2, (xs1) +encoding: + match: 01000<%= aq_bit %><%= rl_bit %>----------<%= current_size[:funct3] %>-----0101111 + variables: + - name: xs2 + location: 24-20 + - name: xs1 + location: 19-15 + - name: xd + location: 11-7 +access: + s: always + u: always + vs: always + vu: always +operation(): | + if (!implemented?(ExtensionName::A) || (MISA_CSR_IMPLEMENTED && (CSR[misa].A == 1'b0))) { + raise (ExceptionCode::IllegalInstruction, mode(), $encoding); + } + +<% if aq -%> + memory_model_acquire(); + +<% end -%> + XReg virtual_address = X[xs1]; + X[xd] = amo<<%= current_size[:operation_bits] %>>(virtual_address, X[xs2]<%= %w[b h w].include?(size) ? "[#{current_size[:bits]-1}:0]" : "" %>, AmoOperation::Or, <%= aq ? "1'b1" : "1'b0" %>, <%= rl ? "1'b1" : "1'b0" %>, $encoding); +<% if rl -%> + + memory_model_release(); +<% end -%> + +# SPDX-SnippetBegin +# SPDX-FileCopyrightText: 2017-2025 Contributors to the RISCV Sail Model +# SPDX-License-Identifier: BSD-2-Clause +sail(): | + { + if extension("A") then { + /* Get the address, X(rs1) (no offset). + * Some extensions perform additional checks on address validity. + */ + match ext_data_get_addr(rs1, zeros(), ReadWrite(Data, Data), width) { + Ext_DataAddr_Error(e) => { ext_handle_data_check_error(e); RETIRE_FAIL }, + Ext_DataAddr_OK(vaddr) => { + match translateAddr(vaddr, ReadWrite(Data, Data)) { + TR_Failure(e, _) => { handle_mem_exception(vaddr, e); RETIRE_FAIL }, + TR_Address(addr, _) => { + let eares : MemoryOpResult(unit) = match (width, sizeof(xlen)) { + (BYTE, _) => mem_write_ea(addr, 1, aq & rl, rl, true), + (HALF, _) => mem_write_ea(addr, 2, aq & rl, rl, true), + (WORD, _) => mem_write_ea(addr, 4, aq & rl, rl, true), + (DOUBLE, 64) => mem_write_ea(addr, 8, aq & rl, rl, true), + _ => internal_error(__FILE__, __LINE__, "Unexpected AMO width") + }; + let is_unsigned : bool = match op { + AMOMINU => true, + AMOMAXU => true, + _ => false + }; + let rs2_val : xlenbits = match width { + BYTE => if is_unsigned then zero_extend(X(rs2)[7..0]) else sign_extend(X(rs2)[7..0]), + HALF => if is_unsigned then zero_extend(X(rs2)[15..0]) else sign_extend(X(rs2)[15..0]), + WORD => if is_unsigned then zero_extend(X(rs2)[31..0]) else sign_extend(X(rs2)[31..0]), + DOUBLE => X(rs2) + }; + match (eares) { + MemException(e) => { handle_mem_exception(vaddr, e); RETIRE_FAIL }, + MemValue(_) => { + let mval : MemoryOpResult(xlenbits) = match (width, sizeof(xlen)) { + (BYTE, _) => extend_value(is_unsigned, mem_read(ReadWrite(Data, Data), addr, 1, aq, aq & rl, true)), + (HALF, _) => extend_value(is_unsigned, mem_read(ReadWrite(Data, Data), addr, 2, aq, aq & rl, true)), + (WORD, _) => extend_value(is_unsigned, mem_read(ReadWrite(Data, Data), addr, 4, aq, aq & rl, true)), + (DOUBLE, 64) => extend_value(is_unsigned, mem_read(ReadWrite(Data, Data), addr, 8, aq, aq & rl, true)), + _ => internal_error(__FILE__, __LINE__, "Unexpected AMO width") + }; + match (mval) { + MemException(e) => { handle_mem_exception(vaddr, e); RETIRE_FAIL }, + MemValue(loaded) => { + let result : xlenbits = + match op { + AMOSWAP => rs2_val, + AMOADD => rs2_val + loaded, + AMOXOR => rs2_val ^ loaded, + AMOAND => rs2_val & loaded, + AMOOR => rs2_val | loaded, + + /* These operations convert bitvectors to integer values using [un]signed, + * and back using to_bits(). + */ + AMOMIN => to_bits(sizeof(xlen), min(signed(rs2_val), signed(loaded))), + AMOMAX => to_bits(sizeof(xlen), max(signed(rs2_val), signed(loaded))), + AMOMINU => to_bits(sizeof(xlen), min(unsigned(rs2_val), unsigned(loaded))), + AMOMAXU => to_bits(sizeof(xlen), max(unsigned(rs2_val), unsigned(loaded))) + }; + let rval : xlenbits = match width { + BYTE => sign_extend(loaded[7..0]), + HALF => sign_extend(loaded[15..0]), + WORD => sign_extend(loaded[31..0]), + DOUBLE => loaded + }; + let wval : MemoryOpResult(bool) = match (width, sizeof(xlen)) { + (BYTE, _) => mem_write_value(addr, 1, result[7..0], aq & rl, rl, true), + (HALF, _) => mem_write_value(addr, 2, result[15..0], aq & rl, rl, true), + (WORD, _) => mem_write_value(addr, 4, result[31..0], aq & rl, rl, true), + (DOUBLE, 64) => mem_write_value(addr, 8, result, aq & rl, rl, true), + _ => internal_error(__FILE__, __LINE__, "Unexpected AMO width") + }; + match (wval) { + MemValue(true) => { X(rd) = rval; RETIRE_SUCCESS }, + MemValue(false) => { internal_error(__FILE__, __LINE__, "AMO got false from mem_write_value") }, + MemException(e) => { handle_mem_exception(vaddr, e); RETIRE_FAIL } + } + } + } + } + } + } + } + } + } + } else { + handle_illegal(); + RETIRE_FAIL + } + } + +# SPDX-SnippetEnd diff --git a/spec/std/isa/inst/Zaamo/amoor.d.aq.yaml b/spec/std/isa/inst/Zaamo/amoor.d.aq.yaml new file mode 100644 index 0000000000..ceb623f25d --- /dev/null +++ b/spec/std/isa/inst/Zaamo/amoor.d.aq.yaml @@ -0,0 +1,140 @@ +# Copyright (c) Qualcomm Technologies, Inc. and/or its subsidiaries. + +# WARNING: This file is auto-generated from spec/std/isa/inst/Zaamo/amoor.SIZE.AQRL.layout# Copyright (c) Abhijit Das(Sukuna0007Abhi) +# SPDX-License-Identifier: BSD-3-Clause-Clear + +# yaml-language-server: $schema=../../../../schemas/inst_schema.json + +$schema: "inst_schema.json#" +kind: instruction +name: amoor.d.aq +long_name: Atomic fetch-and-or doubleword (acquire) +description: | + Atomically with acquire ordering: + + * Load the doubleword at address _xs1_ + * Write the loaded value into _xd_ + * OR the value of register _xs2_ to the loaded value + * Write the result to the address in _xs1_ +definedBy: Zaamo +base: 64 +assembly: xd, xs2, (xs1) +encoding: + match: 0100010----------011-----0101111 + variables: + - name: xs2 + location: 24-20 + - name: xs1 + location: 19-15 + - name: xd + location: 11-7 +access: + s: always + u: always + vs: always + vu: always +operation(): | + if (!implemented?(ExtensionName::A) || (MISA_CSR_IMPLEMENTED && (CSR[misa].A == 1'b0))) { + raise (ExceptionCode::IllegalInstruction, mode(), $encoding); + } + + memory_model_acquire(); + + XReg virtual_address = X[xs1]; + X[xd] = amo<64>(virtual_address, X[xs2], AmoOperation::Or, 1'b1, 1'b0, $encoding); + +# SPDX-SnippetBegin +# SPDX-FileCopyrightText: 2017-2025 Contributors to the RISCV Sail Model +# SPDX-License-Identifier: BSD-2-Clause +sail(): | + { + if extension("A") then { + /* Get the address, X(rs1) (no offset). + * Some extensions perform additional checks on address validity. + */ + match ext_data_get_addr(rs1, zeros(), ReadWrite(Data, Data), width) { + Ext_DataAddr_Error(e) => { ext_handle_data_check_error(e); RETIRE_FAIL }, + Ext_DataAddr_OK(vaddr) => { + match translateAddr(vaddr, ReadWrite(Data, Data)) { + TR_Failure(e, _) => { handle_mem_exception(vaddr, e); RETIRE_FAIL }, + TR_Address(addr, _) => { + let eares : MemoryOpResult(unit) = match (width, sizeof(xlen)) { + (BYTE, _) => mem_write_ea(addr, 1, aq & rl, rl, true), + (HALF, _) => mem_write_ea(addr, 2, aq & rl, rl, true), + (WORD, _) => mem_write_ea(addr, 4, aq & rl, rl, true), + (DOUBLE, 64) => mem_write_ea(addr, 8, aq & rl, rl, true), + _ => internal_error(__FILE__, __LINE__, "Unexpected AMO width") + }; + let is_unsigned : bool = match op { + AMOMINU => true, + AMOMAXU => true, + _ => false + }; + let rs2_val : xlenbits = match width { + BYTE => if is_unsigned then zero_extend(X(rs2)[7..0]) else sign_extend(X(rs2)[7..0]), + HALF => if is_unsigned then zero_extend(X(rs2)[15..0]) else sign_extend(X(rs2)[15..0]), + WORD => if is_unsigned then zero_extend(X(rs2)[31..0]) else sign_extend(X(rs2)[31..0]), + DOUBLE => X(rs2) + }; + match (eares) { + MemException(e) => { handle_mem_exception(vaddr, e); RETIRE_FAIL }, + MemValue(_) => { + let mval : MemoryOpResult(xlenbits) = match (width, sizeof(xlen)) { + (BYTE, _) => extend_value(is_unsigned, mem_read(ReadWrite(Data, Data), addr, 1, aq, aq & rl, true)), + (HALF, _) => extend_value(is_unsigned, mem_read(ReadWrite(Data, Data), addr, 2, aq, aq & rl, true)), + (WORD, _) => extend_value(is_unsigned, mem_read(ReadWrite(Data, Data), addr, 4, aq, aq & rl, true)), + (DOUBLE, 64) => extend_value(is_unsigned, mem_read(ReadWrite(Data, Data), addr, 8, aq, aq & rl, true)), + _ => internal_error(__FILE__, __LINE__, "Unexpected AMO width") + }; + match (mval) { + MemException(e) => { handle_mem_exception(vaddr, e); RETIRE_FAIL }, + MemValue(loaded) => { + let result : xlenbits = + match op { + AMOSWAP => rs2_val, + AMOADD => rs2_val + loaded, + AMOXOR => rs2_val ^ loaded, + AMOAND => rs2_val & loaded, + AMOOR => rs2_val | loaded, + + /* These operations convert bitvectors to integer values using [un]signed, + * and back using to_bits(). + */ + AMOMIN => to_bits(sizeof(xlen), min(signed(rs2_val), signed(loaded))), + AMOMAX => to_bits(sizeof(xlen), max(signed(rs2_val), signed(loaded))), + AMOMINU => to_bits(sizeof(xlen), min(unsigned(rs2_val), unsigned(loaded))), + AMOMAXU => to_bits(sizeof(xlen), max(unsigned(rs2_val), unsigned(loaded))) + }; + let rval : xlenbits = match width { + BYTE => sign_extend(loaded[7..0]), + HALF => sign_extend(loaded[15..0]), + WORD => sign_extend(loaded[31..0]), + DOUBLE => loaded + }; + let wval : MemoryOpResult(bool) = match (width, sizeof(xlen)) { + (BYTE, _) => mem_write_value(addr, 1, result[7..0], aq & rl, rl, true), + (HALF, _) => mem_write_value(addr, 2, result[15..0], aq & rl, rl, true), + (WORD, _) => mem_write_value(addr, 4, result[31..0], aq & rl, rl, true), + (DOUBLE, 64) => mem_write_value(addr, 8, result, aq & rl, rl, true), + _ => internal_error(__FILE__, __LINE__, "Unexpected AMO width") + }; + match (wval) { + MemValue(true) => { X(rd) = rval; RETIRE_SUCCESS }, + MemValue(false) => { internal_error(__FILE__, __LINE__, "AMO got false from mem_write_value") }, + MemException(e) => { handle_mem_exception(vaddr, e); RETIRE_FAIL } + } + } + } + } + } + } + } + } + } + } else { + handle_illegal(); + RETIRE_FAIL + } + } + +# SPDX-SnippetEnd diff --git a/spec/std/isa/inst/Zaamo/amoor.d.aqrl.yaml b/spec/std/isa/inst/Zaamo/amoor.d.aqrl.yaml new file mode 100644 index 0000000000..3df34aa2e2 --- /dev/null +++ b/spec/std/isa/inst/Zaamo/amoor.d.aqrl.yaml @@ -0,0 +1,142 @@ +# Copyright (c) Qualcomm Technologies, Inc. and/or its subsidiaries. + +# WARNING: This file is auto-generated from spec/std/isa/inst/Zaamo/amoor.SIZE.AQRL.layout# Copyright (c) Abhijit Das(Sukuna0007Abhi) +# SPDX-License-Identifier: BSD-3-Clause-Clear + +# yaml-language-server: $schema=../../../../schemas/inst_schema.json + +$schema: "inst_schema.json#" +kind: instruction +name: amoor.d.aqrl +long_name: Atomic fetch-and-or doubleword (acquire-release) +description: | + Atomically with acquire and release ordering: + + * Load the doubleword at address _xs1_ + * Write the loaded value into _xd_ + * OR the value of register _xs2_ to the loaded value + * Write the result to the address in _xs1_ +definedBy: Zaamo +base: 64 +assembly: xd, xs2, (xs1) +encoding: + match: 0100011----------011-----0101111 + variables: + - name: xs2 + location: 24-20 + - name: xs1 + location: 19-15 + - name: xd + location: 11-7 +access: + s: always + u: always + vs: always + vu: always +operation(): | + if (!implemented?(ExtensionName::A) || (MISA_CSR_IMPLEMENTED && (CSR[misa].A == 1'b0))) { + raise (ExceptionCode::IllegalInstruction, mode(), $encoding); + } + + memory_model_acquire(); + + XReg virtual_address = X[xs1]; + X[xd] = amo<64>(virtual_address, X[xs2], AmoOperation::Or, 1'b1, 1'b1, $encoding); + + memory_model_release(); + +# SPDX-SnippetBegin +# SPDX-FileCopyrightText: 2017-2025 Contributors to the RISCV Sail Model +# SPDX-License-Identifier: BSD-2-Clause +sail(): | + { + if extension("A") then { + /* Get the address, X(rs1) (no offset). + * Some extensions perform additional checks on address validity. + */ + match ext_data_get_addr(rs1, zeros(), ReadWrite(Data, Data), width) { + Ext_DataAddr_Error(e) => { ext_handle_data_check_error(e); RETIRE_FAIL }, + Ext_DataAddr_OK(vaddr) => { + match translateAddr(vaddr, ReadWrite(Data, Data)) { + TR_Failure(e, _) => { handle_mem_exception(vaddr, e); RETIRE_FAIL }, + TR_Address(addr, _) => { + let eares : MemoryOpResult(unit) = match (width, sizeof(xlen)) { + (BYTE, _) => mem_write_ea(addr, 1, aq & rl, rl, true), + (HALF, _) => mem_write_ea(addr, 2, aq & rl, rl, true), + (WORD, _) => mem_write_ea(addr, 4, aq & rl, rl, true), + (DOUBLE, 64) => mem_write_ea(addr, 8, aq & rl, rl, true), + _ => internal_error(__FILE__, __LINE__, "Unexpected AMO width") + }; + let is_unsigned : bool = match op { + AMOMINU => true, + AMOMAXU => true, + _ => false + }; + let rs2_val : xlenbits = match width { + BYTE => if is_unsigned then zero_extend(X(rs2)[7..0]) else sign_extend(X(rs2)[7..0]), + HALF => if is_unsigned then zero_extend(X(rs2)[15..0]) else sign_extend(X(rs2)[15..0]), + WORD => if is_unsigned then zero_extend(X(rs2)[31..0]) else sign_extend(X(rs2)[31..0]), + DOUBLE => X(rs2) + }; + match (eares) { + MemException(e) => { handle_mem_exception(vaddr, e); RETIRE_FAIL }, + MemValue(_) => { + let mval : MemoryOpResult(xlenbits) = match (width, sizeof(xlen)) { + (BYTE, _) => extend_value(is_unsigned, mem_read(ReadWrite(Data, Data), addr, 1, aq, aq & rl, true)), + (HALF, _) => extend_value(is_unsigned, mem_read(ReadWrite(Data, Data), addr, 2, aq, aq & rl, true)), + (WORD, _) => extend_value(is_unsigned, mem_read(ReadWrite(Data, Data), addr, 4, aq, aq & rl, true)), + (DOUBLE, 64) => extend_value(is_unsigned, mem_read(ReadWrite(Data, Data), addr, 8, aq, aq & rl, true)), + _ => internal_error(__FILE__, __LINE__, "Unexpected AMO width") + }; + match (mval) { + MemException(e) => { handle_mem_exception(vaddr, e); RETIRE_FAIL }, + MemValue(loaded) => { + let result : xlenbits = + match op { + AMOSWAP => rs2_val, + AMOADD => rs2_val + loaded, + AMOXOR => rs2_val ^ loaded, + AMOAND => rs2_val & loaded, + AMOOR => rs2_val | loaded, + + /* These operations convert bitvectors to integer values using [un]signed, + * and back using to_bits(). + */ + AMOMIN => to_bits(sizeof(xlen), min(signed(rs2_val), signed(loaded))), + AMOMAX => to_bits(sizeof(xlen), max(signed(rs2_val), signed(loaded))), + AMOMINU => to_bits(sizeof(xlen), min(unsigned(rs2_val), unsigned(loaded))), + AMOMAXU => to_bits(sizeof(xlen), max(unsigned(rs2_val), unsigned(loaded))) + }; + let rval : xlenbits = match width { + BYTE => sign_extend(loaded[7..0]), + HALF => sign_extend(loaded[15..0]), + WORD => sign_extend(loaded[31..0]), + DOUBLE => loaded + }; + let wval : MemoryOpResult(bool) = match (width, sizeof(xlen)) { + (BYTE, _) => mem_write_value(addr, 1, result[7..0], aq & rl, rl, true), + (HALF, _) => mem_write_value(addr, 2, result[15..0], aq & rl, rl, true), + (WORD, _) => mem_write_value(addr, 4, result[31..0], aq & rl, rl, true), + (DOUBLE, 64) => mem_write_value(addr, 8, result, aq & rl, rl, true), + _ => internal_error(__FILE__, __LINE__, "Unexpected AMO width") + }; + match (wval) { + MemValue(true) => { X(rd) = rval; RETIRE_SUCCESS }, + MemValue(false) => { internal_error(__FILE__, __LINE__, "AMO got false from mem_write_value") }, + MemException(e) => { handle_mem_exception(vaddr, e); RETIRE_FAIL } + } + } + } + } + } + } + } + } + } + } else { + handle_illegal(); + RETIRE_FAIL + } + } + +# SPDX-SnippetEnd diff --git a/spec/std/isa/inst/Zaamo/amoor.d.rl.yaml b/spec/std/isa/inst/Zaamo/amoor.d.rl.yaml new file mode 100644 index 0000000000..ba1abb50eb --- /dev/null +++ b/spec/std/isa/inst/Zaamo/amoor.d.rl.yaml @@ -0,0 +1,140 @@ +# Copyright (c) Qualcomm Technologies, Inc. and/or its subsidiaries. + +# WARNING: This file is auto-generated from spec/std/isa/inst/Zaamo/amoor.SIZE.AQRL.layout# Copyright (c) Abhijit Das(Sukuna0007Abhi) +# SPDX-License-Identifier: BSD-3-Clause-Clear + +# yaml-language-server: $schema=../../../../schemas/inst_schema.json + +$schema: "inst_schema.json#" +kind: instruction +name: amoor.d.rl +long_name: Atomic fetch-and-or doubleword (release) +description: | + Atomically with release ordering: + + * Load the doubleword at address _xs1_ + * Write the loaded value into _xd_ + * OR the value of register _xs2_ to the loaded value + * Write the result to the address in _xs1_ +definedBy: Zaamo +base: 64 +assembly: xd, xs2, (xs1) +encoding: + match: 0100001----------011-----0101111 + variables: + - name: xs2 + location: 24-20 + - name: xs1 + location: 19-15 + - name: xd + location: 11-7 +access: + s: always + u: always + vs: always + vu: always +operation(): | + if (!implemented?(ExtensionName::A) || (MISA_CSR_IMPLEMENTED && (CSR[misa].A == 1'b0))) { + raise (ExceptionCode::IllegalInstruction, mode(), $encoding); + } + + XReg virtual_address = X[xs1]; + X[xd] = amo<64>(virtual_address, X[xs2], AmoOperation::Or, 1'b0, 1'b1, $encoding); + + memory_model_release(); + +# SPDX-SnippetBegin +# SPDX-FileCopyrightText: 2017-2025 Contributors to the RISCV Sail Model +# SPDX-License-Identifier: BSD-2-Clause +sail(): | + { + if extension("A") then { + /* Get the address, X(rs1) (no offset). + * Some extensions perform additional checks on address validity. + */ + match ext_data_get_addr(rs1, zeros(), ReadWrite(Data, Data), width) { + Ext_DataAddr_Error(e) => { ext_handle_data_check_error(e); RETIRE_FAIL }, + Ext_DataAddr_OK(vaddr) => { + match translateAddr(vaddr, ReadWrite(Data, Data)) { + TR_Failure(e, _) => { handle_mem_exception(vaddr, e); RETIRE_FAIL }, + TR_Address(addr, _) => { + let eares : MemoryOpResult(unit) = match (width, sizeof(xlen)) { + (BYTE, _) => mem_write_ea(addr, 1, aq & rl, rl, true), + (HALF, _) => mem_write_ea(addr, 2, aq & rl, rl, true), + (WORD, _) => mem_write_ea(addr, 4, aq & rl, rl, true), + (DOUBLE, 64) => mem_write_ea(addr, 8, aq & rl, rl, true), + _ => internal_error(__FILE__, __LINE__, "Unexpected AMO width") + }; + let is_unsigned : bool = match op { + AMOMINU => true, + AMOMAXU => true, + _ => false + }; + let rs2_val : xlenbits = match width { + BYTE => if is_unsigned then zero_extend(X(rs2)[7..0]) else sign_extend(X(rs2)[7..0]), + HALF => if is_unsigned then zero_extend(X(rs2)[15..0]) else sign_extend(X(rs2)[15..0]), + WORD => if is_unsigned then zero_extend(X(rs2)[31..0]) else sign_extend(X(rs2)[31..0]), + DOUBLE => X(rs2) + }; + match (eares) { + MemException(e) => { handle_mem_exception(vaddr, e); RETIRE_FAIL }, + MemValue(_) => { + let mval : MemoryOpResult(xlenbits) = match (width, sizeof(xlen)) { + (BYTE, _) => extend_value(is_unsigned, mem_read(ReadWrite(Data, Data), addr, 1, aq, aq & rl, true)), + (HALF, _) => extend_value(is_unsigned, mem_read(ReadWrite(Data, Data), addr, 2, aq, aq & rl, true)), + (WORD, _) => extend_value(is_unsigned, mem_read(ReadWrite(Data, Data), addr, 4, aq, aq & rl, true)), + (DOUBLE, 64) => extend_value(is_unsigned, mem_read(ReadWrite(Data, Data), addr, 8, aq, aq & rl, true)), + _ => internal_error(__FILE__, __LINE__, "Unexpected AMO width") + }; + match (mval) { + MemException(e) => { handle_mem_exception(vaddr, e); RETIRE_FAIL }, + MemValue(loaded) => { + let result : xlenbits = + match op { + AMOSWAP => rs2_val, + AMOADD => rs2_val + loaded, + AMOXOR => rs2_val ^ loaded, + AMOAND => rs2_val & loaded, + AMOOR => rs2_val | loaded, + + /* These operations convert bitvectors to integer values using [un]signed, + * and back using to_bits(). + */ + AMOMIN => to_bits(sizeof(xlen), min(signed(rs2_val), signed(loaded))), + AMOMAX => to_bits(sizeof(xlen), max(signed(rs2_val), signed(loaded))), + AMOMINU => to_bits(sizeof(xlen), min(unsigned(rs2_val), unsigned(loaded))), + AMOMAXU => to_bits(sizeof(xlen), max(unsigned(rs2_val), unsigned(loaded))) + }; + let rval : xlenbits = match width { + BYTE => sign_extend(loaded[7..0]), + HALF => sign_extend(loaded[15..0]), + WORD => sign_extend(loaded[31..0]), + DOUBLE => loaded + }; + let wval : MemoryOpResult(bool) = match (width, sizeof(xlen)) { + (BYTE, _) => mem_write_value(addr, 1, result[7..0], aq & rl, rl, true), + (HALF, _) => mem_write_value(addr, 2, result[15..0], aq & rl, rl, true), + (WORD, _) => mem_write_value(addr, 4, result[31..0], aq & rl, rl, true), + (DOUBLE, 64) => mem_write_value(addr, 8, result, aq & rl, rl, true), + _ => internal_error(__FILE__, __LINE__, "Unexpected AMO width") + }; + match (wval) { + MemValue(true) => { X(rd) = rval; RETIRE_SUCCESS }, + MemValue(false) => { internal_error(__FILE__, __LINE__, "AMO got false from mem_write_value") }, + MemException(e) => { handle_mem_exception(vaddr, e); RETIRE_FAIL } + } + } + } + } + } + } + } + } + } + } else { + handle_illegal(); + RETIRE_FAIL + } + } + +# SPDX-SnippetEnd diff --git a/spec/std/isa/inst/Zaamo/amoor.d.yaml b/spec/std/isa/inst/Zaamo/amoor.d.yaml index 1e9bfe9b46..52e9a9031f 100644 --- a/spec/std/isa/inst/Zaamo/amoor.d.yaml +++ b/spec/std/isa/inst/Zaamo/amoor.d.yaml @@ -1,4 +1,6 @@ # Copyright (c) Qualcomm Technologies, Inc. and/or its subsidiaries. + +# WARNING: This file is auto-generated from spec/std/isa/inst/Zaamo/amoor.SIZE.AQRL.layout# Copyright (c) Abhijit Das(Sukuna0007Abhi) # SPDX-License-Identifier: BSD-3-Clause-Clear # yaml-language-server: $schema=../../../../schemas/inst_schema.json @@ -18,12 +20,8 @@ definedBy: Zaamo base: 64 assembly: xd, xs2, (xs1) encoding: - match: 01000------------011-----0101111 + match: 0100000----------011-----0101111 variables: - - name: aq - location: 26 - - name: rl - location: 25 - name: xs2 location: 24-20 - name: xs1 @@ -36,15 +34,12 @@ access: vs: always vu: always operation(): | - if (implemented?(ExtensionName::A) && (CSR[misa].A == 1'b0)) { - # even though this is a memory operation, the exception occurs before that would be known, - # so mode() is the correct reporting mode rathat than effective_ldst_mode() + if (!implemented?(ExtensionName::A) || (MISA_CSR_IMPLEMENTED && (CSR[misa].A == 1'b0))) { raise (ExceptionCode::IllegalInstruction, mode(), $encoding); } XReg virtual_address = X[xs1]; - - X[xd] = amo<64>(virtual_address, X[xs2], AmoOperation::Or, aq, rl, $encoding); + X[xd] = amo<64>(virtual_address, X[xs2], AmoOperation::Or, 1'b0, 1'b0, $encoding); # SPDX-SnippetBegin # SPDX-FileCopyrightText: 2017-2025 Contributors to the RISCV Sail Model diff --git a/spec/std/isa/inst/Zaamo/amoor.w.aq.yaml b/spec/std/isa/inst/Zaamo/amoor.w.aq.yaml new file mode 100644 index 0000000000..fa062d3f7c --- /dev/null +++ b/spec/std/isa/inst/Zaamo/amoor.w.aq.yaml @@ -0,0 +1,139 @@ +# Copyright (c) Qualcomm Technologies, Inc. and/or its subsidiaries. + +# WARNING: This file is auto-generated from spec/std/isa/inst/Zaamo/amoor.SIZE.AQRL.layout# Copyright (c) Abhijit Das(Sukuna0007Abhi) +# SPDX-License-Identifier: BSD-3-Clause-Clear + +# yaml-language-server: $schema=../../../../schemas/inst_schema.json + +$schema: "inst_schema.json#" +kind: instruction +name: amoor.w.aq +long_name: Atomic fetch-and-or word (acquire) +description: | + Atomically with acquire ordering: + + * Load the word at address _xs1_ + * Write the sign-extended value into _xd_ + * OR the least-significant word of register _xs2_ to the loaded value + * Write the result to the address in _xs1_ +definedBy: Zaamo +assembly: xd, xs2, (xs1) +encoding: + match: 0100010----------010-----0101111 + variables: + - name: xs2 + location: 24-20 + - name: xs1 + location: 19-15 + - name: xd + location: 11-7 +access: + s: always + u: always + vs: always + vu: always +operation(): | + if (!implemented?(ExtensionName::A) || (MISA_CSR_IMPLEMENTED && (CSR[misa].A == 1'b0))) { + raise (ExceptionCode::IllegalInstruction, mode(), $encoding); + } + + memory_model_acquire(); + + XReg virtual_address = X[xs1]; + X[xd] = amo<32>(virtual_address, X[xs2][31:0], AmoOperation::Or, 1'b1, 1'b0, $encoding); + +# SPDX-SnippetBegin +# SPDX-FileCopyrightText: 2017-2025 Contributors to the RISCV Sail Model +# SPDX-License-Identifier: BSD-2-Clause +sail(): | + { + if extension("A") then { + /* Get the address, X(rs1) (no offset). + * Some extensions perform additional checks on address validity. + */ + match ext_data_get_addr(rs1, zeros(), ReadWrite(Data, Data), width) { + Ext_DataAddr_Error(e) => { ext_handle_data_check_error(e); RETIRE_FAIL }, + Ext_DataAddr_OK(vaddr) => { + match translateAddr(vaddr, ReadWrite(Data, Data)) { + TR_Failure(e, _) => { handle_mem_exception(vaddr, e); RETIRE_FAIL }, + TR_Address(addr, _) => { + let eares : MemoryOpResult(unit) = match (width, sizeof(xlen)) { + (BYTE, _) => mem_write_ea(addr, 1, aq & rl, rl, true), + (HALF, _) => mem_write_ea(addr, 2, aq & rl, rl, true), + (WORD, _) => mem_write_ea(addr, 4, aq & rl, rl, true), + (DOUBLE, 64) => mem_write_ea(addr, 8, aq & rl, rl, true), + _ => internal_error(__FILE__, __LINE__, "Unexpected AMO width") + }; + let is_unsigned : bool = match op { + AMOMINU => true, + AMOMAXU => true, + _ => false + }; + let rs2_val : xlenbits = match width { + BYTE => if is_unsigned then zero_extend(X(rs2)[7..0]) else sign_extend(X(rs2)[7..0]), + HALF => if is_unsigned then zero_extend(X(rs2)[15..0]) else sign_extend(X(rs2)[15..0]), + WORD => if is_unsigned then zero_extend(X(rs2)[31..0]) else sign_extend(X(rs2)[31..0]), + DOUBLE => X(rs2) + }; + match (eares) { + MemException(e) => { handle_mem_exception(vaddr, e); RETIRE_FAIL }, + MemValue(_) => { + let mval : MemoryOpResult(xlenbits) = match (width, sizeof(xlen)) { + (BYTE, _) => extend_value(is_unsigned, mem_read(ReadWrite(Data, Data), addr, 1, aq, aq & rl, true)), + (HALF, _) => extend_value(is_unsigned, mem_read(ReadWrite(Data, Data), addr, 2, aq, aq & rl, true)), + (WORD, _) => extend_value(is_unsigned, mem_read(ReadWrite(Data, Data), addr, 4, aq, aq & rl, true)), + (DOUBLE, 64) => extend_value(is_unsigned, mem_read(ReadWrite(Data, Data), addr, 8, aq, aq & rl, true)), + _ => internal_error(__FILE__, __LINE__, "Unexpected AMO width") + }; + match (mval) { + MemException(e) => { handle_mem_exception(vaddr, e); RETIRE_FAIL }, + MemValue(loaded) => { + let result : xlenbits = + match op { + AMOSWAP => rs2_val, + AMOADD => rs2_val + loaded, + AMOXOR => rs2_val ^ loaded, + AMOAND => rs2_val & loaded, + AMOOR => rs2_val | loaded, + + /* These operations convert bitvectors to integer values using [un]signed, + * and back using to_bits(). + */ + AMOMIN => to_bits(sizeof(xlen), min(signed(rs2_val), signed(loaded))), + AMOMAX => to_bits(sizeof(xlen), max(signed(rs2_val), signed(loaded))), + AMOMINU => to_bits(sizeof(xlen), min(unsigned(rs2_val), unsigned(loaded))), + AMOMAXU => to_bits(sizeof(xlen), max(unsigned(rs2_val), unsigned(loaded))) + }; + let rval : xlenbits = match width { + BYTE => sign_extend(loaded[7..0]), + HALF => sign_extend(loaded[15..0]), + WORD => sign_extend(loaded[31..0]), + DOUBLE => loaded + }; + let wval : MemoryOpResult(bool) = match (width, sizeof(xlen)) { + (BYTE, _) => mem_write_value(addr, 1, result[7..0], aq & rl, rl, true), + (HALF, _) => mem_write_value(addr, 2, result[15..0], aq & rl, rl, true), + (WORD, _) => mem_write_value(addr, 4, result[31..0], aq & rl, rl, true), + (DOUBLE, 64) => mem_write_value(addr, 8, result, aq & rl, rl, true), + _ => internal_error(__FILE__, __LINE__, "Unexpected AMO width") + }; + match (wval) { + MemValue(true) => { X(rd) = rval; RETIRE_SUCCESS }, + MemValue(false) => { internal_error(__FILE__, __LINE__, "AMO got false from mem_write_value") }, + MemException(e) => { handle_mem_exception(vaddr, e); RETIRE_FAIL } + } + } + } + } + } + } + } + } + } + } else { + handle_illegal(); + RETIRE_FAIL + } + } + +# SPDX-SnippetEnd diff --git a/spec/std/isa/inst/Zaamo/amoor.w.aqrl.yaml b/spec/std/isa/inst/Zaamo/amoor.w.aqrl.yaml new file mode 100644 index 0000000000..aec24e9320 --- /dev/null +++ b/spec/std/isa/inst/Zaamo/amoor.w.aqrl.yaml @@ -0,0 +1,141 @@ +# Copyright (c) Qualcomm Technologies, Inc. and/or its subsidiaries. + +# WARNING: This file is auto-generated from spec/std/isa/inst/Zaamo/amoor.SIZE.AQRL.layout# Copyright (c) Abhijit Das(Sukuna0007Abhi) +# SPDX-License-Identifier: BSD-3-Clause-Clear + +# yaml-language-server: $schema=../../../../schemas/inst_schema.json + +$schema: "inst_schema.json#" +kind: instruction +name: amoor.w.aqrl +long_name: Atomic fetch-and-or word (acquire-release) +description: | + Atomically with acquire and release ordering: + + * Load the word at address _xs1_ + * Write the sign-extended value into _xd_ + * OR the least-significant word of register _xs2_ to the loaded value + * Write the result to the address in _xs1_ +definedBy: Zaamo +assembly: xd, xs2, (xs1) +encoding: + match: 0100011----------010-----0101111 + variables: + - name: xs2 + location: 24-20 + - name: xs1 + location: 19-15 + - name: xd + location: 11-7 +access: + s: always + u: always + vs: always + vu: always +operation(): | + if (!implemented?(ExtensionName::A) || (MISA_CSR_IMPLEMENTED && (CSR[misa].A == 1'b0))) { + raise (ExceptionCode::IllegalInstruction, mode(), $encoding); + } + + memory_model_acquire(); + + XReg virtual_address = X[xs1]; + X[xd] = amo<32>(virtual_address, X[xs2][31:0], AmoOperation::Or, 1'b1, 1'b1, $encoding); + + memory_model_release(); + +# SPDX-SnippetBegin +# SPDX-FileCopyrightText: 2017-2025 Contributors to the RISCV Sail Model +# SPDX-License-Identifier: BSD-2-Clause +sail(): | + { + if extension("A") then { + /* Get the address, X(rs1) (no offset). + * Some extensions perform additional checks on address validity. + */ + match ext_data_get_addr(rs1, zeros(), ReadWrite(Data, Data), width) { + Ext_DataAddr_Error(e) => { ext_handle_data_check_error(e); RETIRE_FAIL }, + Ext_DataAddr_OK(vaddr) => { + match translateAddr(vaddr, ReadWrite(Data, Data)) { + TR_Failure(e, _) => { handle_mem_exception(vaddr, e); RETIRE_FAIL }, + TR_Address(addr, _) => { + let eares : MemoryOpResult(unit) = match (width, sizeof(xlen)) { + (BYTE, _) => mem_write_ea(addr, 1, aq & rl, rl, true), + (HALF, _) => mem_write_ea(addr, 2, aq & rl, rl, true), + (WORD, _) => mem_write_ea(addr, 4, aq & rl, rl, true), + (DOUBLE, 64) => mem_write_ea(addr, 8, aq & rl, rl, true), + _ => internal_error(__FILE__, __LINE__, "Unexpected AMO width") + }; + let is_unsigned : bool = match op { + AMOMINU => true, + AMOMAXU => true, + _ => false + }; + let rs2_val : xlenbits = match width { + BYTE => if is_unsigned then zero_extend(X(rs2)[7..0]) else sign_extend(X(rs2)[7..0]), + HALF => if is_unsigned then zero_extend(X(rs2)[15..0]) else sign_extend(X(rs2)[15..0]), + WORD => if is_unsigned then zero_extend(X(rs2)[31..0]) else sign_extend(X(rs2)[31..0]), + DOUBLE => X(rs2) + }; + match (eares) { + MemException(e) => { handle_mem_exception(vaddr, e); RETIRE_FAIL }, + MemValue(_) => { + let mval : MemoryOpResult(xlenbits) = match (width, sizeof(xlen)) { + (BYTE, _) => extend_value(is_unsigned, mem_read(ReadWrite(Data, Data), addr, 1, aq, aq & rl, true)), + (HALF, _) => extend_value(is_unsigned, mem_read(ReadWrite(Data, Data), addr, 2, aq, aq & rl, true)), + (WORD, _) => extend_value(is_unsigned, mem_read(ReadWrite(Data, Data), addr, 4, aq, aq & rl, true)), + (DOUBLE, 64) => extend_value(is_unsigned, mem_read(ReadWrite(Data, Data), addr, 8, aq, aq & rl, true)), + _ => internal_error(__FILE__, __LINE__, "Unexpected AMO width") + }; + match (mval) { + MemException(e) => { handle_mem_exception(vaddr, e); RETIRE_FAIL }, + MemValue(loaded) => { + let result : xlenbits = + match op { + AMOSWAP => rs2_val, + AMOADD => rs2_val + loaded, + AMOXOR => rs2_val ^ loaded, + AMOAND => rs2_val & loaded, + AMOOR => rs2_val | loaded, + + /* These operations convert bitvectors to integer values using [un]signed, + * and back using to_bits(). + */ + AMOMIN => to_bits(sizeof(xlen), min(signed(rs2_val), signed(loaded))), + AMOMAX => to_bits(sizeof(xlen), max(signed(rs2_val), signed(loaded))), + AMOMINU => to_bits(sizeof(xlen), min(unsigned(rs2_val), unsigned(loaded))), + AMOMAXU => to_bits(sizeof(xlen), max(unsigned(rs2_val), unsigned(loaded))) + }; + let rval : xlenbits = match width { + BYTE => sign_extend(loaded[7..0]), + HALF => sign_extend(loaded[15..0]), + WORD => sign_extend(loaded[31..0]), + DOUBLE => loaded + }; + let wval : MemoryOpResult(bool) = match (width, sizeof(xlen)) { + (BYTE, _) => mem_write_value(addr, 1, result[7..0], aq & rl, rl, true), + (HALF, _) => mem_write_value(addr, 2, result[15..0], aq & rl, rl, true), + (WORD, _) => mem_write_value(addr, 4, result[31..0], aq & rl, rl, true), + (DOUBLE, 64) => mem_write_value(addr, 8, result, aq & rl, rl, true), + _ => internal_error(__FILE__, __LINE__, "Unexpected AMO width") + }; + match (wval) { + MemValue(true) => { X(rd) = rval; RETIRE_SUCCESS }, + MemValue(false) => { internal_error(__FILE__, __LINE__, "AMO got false from mem_write_value") }, + MemException(e) => { handle_mem_exception(vaddr, e); RETIRE_FAIL } + } + } + } + } + } + } + } + } + } + } else { + handle_illegal(); + RETIRE_FAIL + } + } + +# SPDX-SnippetEnd diff --git a/spec/std/isa/inst/Zaamo/amoor.w.rl.yaml b/spec/std/isa/inst/Zaamo/amoor.w.rl.yaml new file mode 100644 index 0000000000..f950f99869 --- /dev/null +++ b/spec/std/isa/inst/Zaamo/amoor.w.rl.yaml @@ -0,0 +1,139 @@ +# Copyright (c) Qualcomm Technologies, Inc. and/or its subsidiaries. + +# WARNING: This file is auto-generated from spec/std/isa/inst/Zaamo/amoor.SIZE.AQRL.layout# Copyright (c) Abhijit Das(Sukuna0007Abhi) +# SPDX-License-Identifier: BSD-3-Clause-Clear + +# yaml-language-server: $schema=../../../../schemas/inst_schema.json + +$schema: "inst_schema.json#" +kind: instruction +name: amoor.w.rl +long_name: Atomic fetch-and-or word (release) +description: | + Atomically with release ordering: + + * Load the word at address _xs1_ + * Write the sign-extended value into _xd_ + * OR the least-significant word of register _xs2_ to the loaded value + * Write the result to the address in _xs1_ +definedBy: Zaamo +assembly: xd, xs2, (xs1) +encoding: + match: 0100001----------010-----0101111 + variables: + - name: xs2 + location: 24-20 + - name: xs1 + location: 19-15 + - name: xd + location: 11-7 +access: + s: always + u: always + vs: always + vu: always +operation(): | + if (!implemented?(ExtensionName::A) || (MISA_CSR_IMPLEMENTED && (CSR[misa].A == 1'b0))) { + raise (ExceptionCode::IllegalInstruction, mode(), $encoding); + } + + XReg virtual_address = X[xs1]; + X[xd] = amo<32>(virtual_address, X[xs2][31:0], AmoOperation::Or, 1'b0, 1'b1, $encoding); + + memory_model_release(); + +# SPDX-SnippetBegin +# SPDX-FileCopyrightText: 2017-2025 Contributors to the RISCV Sail Model +# SPDX-License-Identifier: BSD-2-Clause +sail(): | + { + if extension("A") then { + /* Get the address, X(rs1) (no offset). + * Some extensions perform additional checks on address validity. + */ + match ext_data_get_addr(rs1, zeros(), ReadWrite(Data, Data), width) { + Ext_DataAddr_Error(e) => { ext_handle_data_check_error(e); RETIRE_FAIL }, + Ext_DataAddr_OK(vaddr) => { + match translateAddr(vaddr, ReadWrite(Data, Data)) { + TR_Failure(e, _) => { handle_mem_exception(vaddr, e); RETIRE_FAIL }, + TR_Address(addr, _) => { + let eares : MemoryOpResult(unit) = match (width, sizeof(xlen)) { + (BYTE, _) => mem_write_ea(addr, 1, aq & rl, rl, true), + (HALF, _) => mem_write_ea(addr, 2, aq & rl, rl, true), + (WORD, _) => mem_write_ea(addr, 4, aq & rl, rl, true), + (DOUBLE, 64) => mem_write_ea(addr, 8, aq & rl, rl, true), + _ => internal_error(__FILE__, __LINE__, "Unexpected AMO width") + }; + let is_unsigned : bool = match op { + AMOMINU => true, + AMOMAXU => true, + _ => false + }; + let rs2_val : xlenbits = match width { + BYTE => if is_unsigned then zero_extend(X(rs2)[7..0]) else sign_extend(X(rs2)[7..0]), + HALF => if is_unsigned then zero_extend(X(rs2)[15..0]) else sign_extend(X(rs2)[15..0]), + WORD => if is_unsigned then zero_extend(X(rs2)[31..0]) else sign_extend(X(rs2)[31..0]), + DOUBLE => X(rs2) + }; + match (eares) { + MemException(e) => { handle_mem_exception(vaddr, e); RETIRE_FAIL }, + MemValue(_) => { + let mval : MemoryOpResult(xlenbits) = match (width, sizeof(xlen)) { + (BYTE, _) => extend_value(is_unsigned, mem_read(ReadWrite(Data, Data), addr, 1, aq, aq & rl, true)), + (HALF, _) => extend_value(is_unsigned, mem_read(ReadWrite(Data, Data), addr, 2, aq, aq & rl, true)), + (WORD, _) => extend_value(is_unsigned, mem_read(ReadWrite(Data, Data), addr, 4, aq, aq & rl, true)), + (DOUBLE, 64) => extend_value(is_unsigned, mem_read(ReadWrite(Data, Data), addr, 8, aq, aq & rl, true)), + _ => internal_error(__FILE__, __LINE__, "Unexpected AMO width") + }; + match (mval) { + MemException(e) => { handle_mem_exception(vaddr, e); RETIRE_FAIL }, + MemValue(loaded) => { + let result : xlenbits = + match op { + AMOSWAP => rs2_val, + AMOADD => rs2_val + loaded, + AMOXOR => rs2_val ^ loaded, + AMOAND => rs2_val & loaded, + AMOOR => rs2_val | loaded, + + /* These operations convert bitvectors to integer values using [un]signed, + * and back using to_bits(). + */ + AMOMIN => to_bits(sizeof(xlen), min(signed(rs2_val), signed(loaded))), + AMOMAX => to_bits(sizeof(xlen), max(signed(rs2_val), signed(loaded))), + AMOMINU => to_bits(sizeof(xlen), min(unsigned(rs2_val), unsigned(loaded))), + AMOMAXU => to_bits(sizeof(xlen), max(unsigned(rs2_val), unsigned(loaded))) + }; + let rval : xlenbits = match width { + BYTE => sign_extend(loaded[7..0]), + HALF => sign_extend(loaded[15..0]), + WORD => sign_extend(loaded[31..0]), + DOUBLE => loaded + }; + let wval : MemoryOpResult(bool) = match (width, sizeof(xlen)) { + (BYTE, _) => mem_write_value(addr, 1, result[7..0], aq & rl, rl, true), + (HALF, _) => mem_write_value(addr, 2, result[15..0], aq & rl, rl, true), + (WORD, _) => mem_write_value(addr, 4, result[31..0], aq & rl, rl, true), + (DOUBLE, 64) => mem_write_value(addr, 8, result, aq & rl, rl, true), + _ => internal_error(__FILE__, __LINE__, "Unexpected AMO width") + }; + match (wval) { + MemValue(true) => { X(rd) = rval; RETIRE_SUCCESS }, + MemValue(false) => { internal_error(__FILE__, __LINE__, "AMO got false from mem_write_value") }, + MemException(e) => { handle_mem_exception(vaddr, e); RETIRE_FAIL } + } + } + } + } + } + } + } + } + } + } else { + handle_illegal(); + RETIRE_FAIL + } + } + +# SPDX-SnippetEnd diff --git a/spec/std/isa/inst/Zaamo/amoor.w.yaml b/spec/std/isa/inst/Zaamo/amoor.w.yaml index bf983a95f7..5127fbcceb 100644 --- a/spec/std/isa/inst/Zaamo/amoor.w.yaml +++ b/spec/std/isa/inst/Zaamo/amoor.w.yaml @@ -1,4 +1,6 @@ # Copyright (c) Qualcomm Technologies, Inc. and/or its subsidiaries. + +# WARNING: This file is auto-generated from spec/std/isa/inst/Zaamo/amoor.SIZE.AQRL.layout# Copyright (c) Abhijit Das(Sukuna0007Abhi) # SPDX-License-Identifier: BSD-3-Clause-Clear # yaml-language-server: $schema=../../../../schemas/inst_schema.json @@ -17,12 +19,8 @@ description: | definedBy: Zaamo assembly: xd, xs2, (xs1) encoding: - match: 01000------------010-----0101111 + match: 0100000----------010-----0101111 variables: - - name: aq - location: 26 - - name: rl - location: 25 - name: xs2 location: 24-20 - name: xs1 @@ -35,15 +33,12 @@ access: vs: always vu: always operation(): | - if (implemented?(ExtensionName::A) && (CSR[misa].A == 1'b0)) { - # even though this is a memory operation, the exception occurs before that would be known, - # so mode() is the correct reporting mode rathat than effective_ldst_mode() + if (!implemented?(ExtensionName::A) || (MISA_CSR_IMPLEMENTED && (CSR[misa].A == 1'b0))) { raise (ExceptionCode::IllegalInstruction, mode(), $encoding); } XReg virtual_address = X[xs1]; - - X[xd] = amo<32>(virtual_address, X[xs2][31:0], AmoOperation::Or, aq, rl, $encoding); + X[xd] = amo<32>(virtual_address, X[xs2][31:0], AmoOperation::Or, 1'b0, 1'b0, $encoding); # SPDX-SnippetBegin # SPDX-FileCopyrightText: 2017-2025 Contributors to the RISCV Sail Model diff --git a/spec/std/isa/inst/Zaamo/amoswap.SIZE.AQRL.layout b/spec/std/isa/inst/Zaamo/amoswap.SIZE.AQRL.layout new file mode 100644 index 0000000000..cc2b483786 --- /dev/null +++ b/spec/std/isa/inst/Zaamo/amoswap.SIZE.AQRL.layout @@ -0,0 +1,174 @@ +# Copyright (c) Qualcomm Technologies, Inc. and/or its subsidiaries. +# Copyright (c) Abhijit Das(Sukuna0007Abhi) +# SPDX-License-Identifier: BSD-3-Clause-Clear + +# yaml-language-server: $schema=../../../../schemas/inst_schema.json +<%- + raise "'size' must be defined as 'b', 'h', 'w', or 'd'" unless %w[b h w d].include?(size) + raise "'aq' must be defined as true or false" unless [true, false].include?(aq) + raise "'rl' must be defined as true or false" unless [true, false].include?(rl) + + size_info = { + "b" => { name: "byte", bits: 8, funct3: "000", operation_bits: "8" }, + "h" => { name: "halfword", bits: 16, funct3: "001", operation_bits: "16" }, + "w" => { name: "word", bits: 32, funct3: "010", operation_bits: "32" }, + "d" => { name: "doubleword", bits: 64, funct3: "011", operation_bits: "64" } + } + + current_size = size_info[size] + + # Generate instruction name suffix based on aq/rl + aq_rl_suffix = "" + if aq && rl + aq_rl_suffix = ".aqrl" + elsif aq + aq_rl_suffix = ".aq" + elsif rl + aq_rl_suffix = ".rl" + end + + # Generate match string with fixed aq/rl bits + aq_bit = aq ? "1" : "0" + rl_bit = rl ? "1" : "0" +-%> + +$schema: "inst_schema.json#" +kind: instruction +name: amoswap.<%= size %><%= aq_rl_suffix %> +long_name: Atomic SWAP <%= current_size[:name] %><%= aq && rl ? " (acquire-release)" : (aq ? " (acquire)" : (rl ? " (release)" : "")) %> +description: | + Atomically<%= aq && rl ? " with acquire and release ordering" : (aq ? " with acquire ordering" : (rl ? " with release ordering" : "")) %>: + + * Load the <%= current_size[:name] %> at address _xs1_ + * Write the <%= %w[b h].include?(size) ? "sign-extended value" : (size == "w" ? "sign-extended value" : "loaded value") %> into _xd_ + * Store the <%= %w[b h w].include?(size) ? "least-significant #{current_size[:name]} of register" : "value of register" %> _xs2_ to the address in _xs1_ +definedBy: <%= %w[b h].include?(size) ? "Zabha" : "Zaamo" %> +<%- if size == "d" -%> +base: 64 +<%- end -%> +assembly: xd, xs2, (xs1) +encoding: + match: 00001<%= aq_bit %><%= rl_bit %>----------<%= current_size[:funct3] %>-----0101111 + variables: + - name: xs2 + location: 24-20 + - name: xs1 + location: 19-15 + - name: xd + location: 11-7 +access: + s: always + u: always + vs: always + vu: always +operation(): | + if (!implemented?(ExtensionName::A) || (MISA_CSR_IMPLEMENTED && (CSR[misa].A == 1'b0))) { + raise (ExceptionCode::IllegalInstruction, mode(), $encoding); + } + +<% if aq -%> + memory_model_acquire(); + +<% end -%> + XReg virtual_address = X[xs1]; + X[xd] = amo<<%= current_size[:operation_bits] %>>(virtual_address, X[xs2]<%= %w[b h w].include?(size) ? "[#{current_size[:bits]-1}:0]" : "" %>, AmoOperation::Swap, <%= aq ? "1'b1" : "1'b0" %>, <%= rl ? "1'b1" : "1'b0" %>, $encoding); +<% if rl -%> + + memory_model_release(); +<% end -%> + +# SPDX-SnippetBegin +# SPDX-FileCopyrightText: 2017-2025 Contributors to the RISCV Sail Model +# SPDX-License-Identifier: BSD-2-Clause +sail(): | + { + if extension("A") then { + /* Get the address, X(rs1) (no offset). + * Some extensions perform additional checks on address validity. + */ + match ext_data_get_addr(rs1, zeros(), ReadWrite(Data, Data), width) { + Ext_DataAddr_Error(e) => { ext_handle_data_check_error(e); RETIRE_FAIL }, + Ext_DataAddr_OK(vaddr) => { + match translateAddr(vaddr, ReadWrite(Data, Data)) { + TR_Failure(e, _) => { handle_mem_exception(vaddr, e); RETIRE_FAIL }, + TR_Address(addr, _) => { + let eares : MemoryOpResult(unit) = match (width, sizeof(xlen)) { + (BYTE, _) => mem_write_ea(addr, 1, aq & rl, rl, true), + (HALF, _) => mem_write_ea(addr, 2, aq & rl, rl, true), + (WORD, _) => mem_write_ea(addr, 4, aq & rl, rl, true), + (DOUBLE, 64) => mem_write_ea(addr, 8, aq & rl, rl, true), + _ => internal_error(__FILE__, __LINE__, "Unexpected AMO width") + }; + let is_unsigned : bool = match op { + AMOMINU => true, + AMOMAXU => true, + _ => false + }; + let rs2_val : xlenbits = match width { + BYTE => if is_unsigned then zero_extend(X(rs2)[7..0]) else sign_extend(X(rs2)[7..0]), + HALF => if is_unsigned then zero_extend(X(rs2)[15..0]) else sign_extend(X(rs2)[15..0]), + WORD => if is_unsigned then zero_extend(X(rs2)[31..0]) else sign_extend(X(rs2)[31..0]), + DOUBLE => X(rs2) + }; + match (eares) { + MemException(e) => { handle_mem_exception(vaddr, e); RETIRE_FAIL }, + MemValue(_) => { + let mval : MemoryOpResult(xlenbits) = match (width, sizeof(xlen)) { + (BYTE, _) => extend_value(is_unsigned, mem_read(ReadWrite(Data, Data), addr, 1, aq, aq & rl, true)), + (HALF, _) => extend_value(is_unsigned, mem_read(ReadWrite(Data, Data), addr, 2, aq, aq & rl, true)), + (WORD, _) => extend_value(is_unsigned, mem_read(ReadWrite(Data, Data), addr, 4, aq, aq & rl, true)), + (DOUBLE, 64) => extend_value(is_unsigned, mem_read(ReadWrite(Data, Data), addr, 8, aq, aq & rl, true)), + _ => internal_error(__FILE__, __LINE__, "Unexpected AMO width") + }; + match (mval) { + MemException(e) => { handle_mem_exception(vaddr, e); RETIRE_FAIL }, + MemValue(loaded) => { + let result : xlenbits = + match op { + AMOSWAP => rs2_val, + AMOADD => rs2_val + loaded, + AMOXOR => rs2_val ^ loaded, + AMOAND => rs2_val & loaded, + AMOOR => rs2_val | loaded, + + /* These operations convert bitvectors to integer values using [un]signed, + * and back using to_bits(). + */ + AMOMIN => to_bits(sizeof(xlen), min(signed(rs2_val), signed(loaded))), + AMOMAX => to_bits(sizeof(xlen), max(signed(rs2_val), signed(loaded))), + AMOMINU => to_bits(sizeof(xlen), min(unsigned(rs2_val), unsigned(loaded))), + AMOMAXU => to_bits(sizeof(xlen), max(unsigned(rs2_val), unsigned(loaded))) + }; + let rval : xlenbits = match width { + BYTE => sign_extend(loaded[7..0]), + HALF => sign_extend(loaded[15..0]), + WORD => sign_extend(loaded[31..0]), + DOUBLE => loaded + }; + let wval : MemoryOpResult(bool) = match (width, sizeof(xlen)) { + (BYTE, _) => mem_write_value(addr, 1, result[7..0], aq & rl, rl, true), + (HALF, _) => mem_write_value(addr, 2, result[15..0], aq & rl, rl, true), + (WORD, _) => mem_write_value(addr, 4, result[31..0], aq & rl, rl, true), + (DOUBLE, 64) => mem_write_value(addr, 8, result, aq & rl, rl, true), + _ => internal_error(__FILE__, __LINE__, "Unexpected AMO width") + }; + match (wval) { + MemValue(true) => { X(rd) = rval; RETIRE_SUCCESS }, + MemValue(false) => { internal_error(__FILE__, __LINE__, "AMO got false from mem_write_value") }, + MemException(e) => { handle_mem_exception(vaddr, e); RETIRE_FAIL } + } + } + } + } + } + } + } + } + } + } else { + handle_illegal(); + RETIRE_FAIL + } + } + +# SPDX-SnippetEnd diff --git a/spec/std/isa/inst/Zaamo/amoswap.d.aq.yaml b/spec/std/isa/inst/Zaamo/amoswap.d.aq.yaml new file mode 100644 index 0000000000..4b4cfec3aa --- /dev/null +++ b/spec/std/isa/inst/Zaamo/amoswap.d.aq.yaml @@ -0,0 +1,139 @@ +# Copyright (c) Qualcomm Technologies, Inc. and/or its subsidiaries. + +# WARNING: This file is auto-generated from spec/std/isa/inst/Zaamo/amoswap.SIZE.AQRL.layout# Copyright (c) Abhijit Das(Sukuna0007Abhi) +# SPDX-License-Identifier: BSD-3-Clause-Clear + +# yaml-language-server: $schema=../../../../schemas/inst_schema.json + +$schema: "inst_schema.json#" +kind: instruction +name: amoswap.d.aq +long_name: Atomic SWAP doubleword (acquire) +description: | + Atomically with acquire ordering: + + * Load the doubleword at address _xs1_ + * Write the loaded value into _xd_ + * Store the value of register _xs2_ to the address in _xs1_ +definedBy: Zaamo +base: 64 +assembly: xd, xs2, (xs1) +encoding: + match: 0000110----------011-----0101111 + variables: + - name: xs2 + location: 24-20 + - name: xs1 + location: 19-15 + - name: xd + location: 11-7 +access: + s: always + u: always + vs: always + vu: always +operation(): | + if (!implemented?(ExtensionName::A) || (MISA_CSR_IMPLEMENTED && (CSR[misa].A == 1'b0))) { + raise (ExceptionCode::IllegalInstruction, mode(), $encoding); + } + + memory_model_acquire(); + + XReg virtual_address = X[xs1]; + X[xd] = amo<64>(virtual_address, X[xs2], AmoOperation::Swap, 1'b1, 1'b0, $encoding); + +# SPDX-SnippetBegin +# SPDX-FileCopyrightText: 2017-2025 Contributors to the RISCV Sail Model +# SPDX-License-Identifier: BSD-2-Clause +sail(): | + { + if extension("A") then { + /* Get the address, X(rs1) (no offset). + * Some extensions perform additional checks on address validity. + */ + match ext_data_get_addr(rs1, zeros(), ReadWrite(Data, Data), width) { + Ext_DataAddr_Error(e) => { ext_handle_data_check_error(e); RETIRE_FAIL }, + Ext_DataAddr_OK(vaddr) => { + match translateAddr(vaddr, ReadWrite(Data, Data)) { + TR_Failure(e, _) => { handle_mem_exception(vaddr, e); RETIRE_FAIL }, + TR_Address(addr, _) => { + let eares : MemoryOpResult(unit) = match (width, sizeof(xlen)) { + (BYTE, _) => mem_write_ea(addr, 1, aq & rl, rl, true), + (HALF, _) => mem_write_ea(addr, 2, aq & rl, rl, true), + (WORD, _) => mem_write_ea(addr, 4, aq & rl, rl, true), + (DOUBLE, 64) => mem_write_ea(addr, 8, aq & rl, rl, true), + _ => internal_error(__FILE__, __LINE__, "Unexpected AMO width") + }; + let is_unsigned : bool = match op { + AMOMINU => true, + AMOMAXU => true, + _ => false + }; + let rs2_val : xlenbits = match width { + BYTE => if is_unsigned then zero_extend(X(rs2)[7..0]) else sign_extend(X(rs2)[7..0]), + HALF => if is_unsigned then zero_extend(X(rs2)[15..0]) else sign_extend(X(rs2)[15..0]), + WORD => if is_unsigned then zero_extend(X(rs2)[31..0]) else sign_extend(X(rs2)[31..0]), + DOUBLE => X(rs2) + }; + match (eares) { + MemException(e) => { handle_mem_exception(vaddr, e); RETIRE_FAIL }, + MemValue(_) => { + let mval : MemoryOpResult(xlenbits) = match (width, sizeof(xlen)) { + (BYTE, _) => extend_value(is_unsigned, mem_read(ReadWrite(Data, Data), addr, 1, aq, aq & rl, true)), + (HALF, _) => extend_value(is_unsigned, mem_read(ReadWrite(Data, Data), addr, 2, aq, aq & rl, true)), + (WORD, _) => extend_value(is_unsigned, mem_read(ReadWrite(Data, Data), addr, 4, aq, aq & rl, true)), + (DOUBLE, 64) => extend_value(is_unsigned, mem_read(ReadWrite(Data, Data), addr, 8, aq, aq & rl, true)), + _ => internal_error(__FILE__, __LINE__, "Unexpected AMO width") + }; + match (mval) { + MemException(e) => { handle_mem_exception(vaddr, e); RETIRE_FAIL }, + MemValue(loaded) => { + let result : xlenbits = + match op { + AMOSWAP => rs2_val, + AMOADD => rs2_val + loaded, + AMOXOR => rs2_val ^ loaded, + AMOAND => rs2_val & loaded, + AMOOR => rs2_val | loaded, + + /* These operations convert bitvectors to integer values using [un]signed, + * and back using to_bits(). + */ + AMOMIN => to_bits(sizeof(xlen), min(signed(rs2_val), signed(loaded))), + AMOMAX => to_bits(sizeof(xlen), max(signed(rs2_val), signed(loaded))), + AMOMINU => to_bits(sizeof(xlen), min(unsigned(rs2_val), unsigned(loaded))), + AMOMAXU => to_bits(sizeof(xlen), max(unsigned(rs2_val), unsigned(loaded))) + }; + let rval : xlenbits = match width { + BYTE => sign_extend(loaded[7..0]), + HALF => sign_extend(loaded[15..0]), + WORD => sign_extend(loaded[31..0]), + DOUBLE => loaded + }; + let wval : MemoryOpResult(bool) = match (width, sizeof(xlen)) { + (BYTE, _) => mem_write_value(addr, 1, result[7..0], aq & rl, rl, true), + (HALF, _) => mem_write_value(addr, 2, result[15..0], aq & rl, rl, true), + (WORD, _) => mem_write_value(addr, 4, result[31..0], aq & rl, rl, true), + (DOUBLE, 64) => mem_write_value(addr, 8, result, aq & rl, rl, true), + _ => internal_error(__FILE__, __LINE__, "Unexpected AMO width") + }; + match (wval) { + MemValue(true) => { X(rd) = rval; RETIRE_SUCCESS }, + MemValue(false) => { internal_error(__FILE__, __LINE__, "AMO got false from mem_write_value") }, + MemException(e) => { handle_mem_exception(vaddr, e); RETIRE_FAIL } + } + } + } + } + } + } + } + } + } + } else { + handle_illegal(); + RETIRE_FAIL + } + } + +# SPDX-SnippetEnd diff --git a/spec/std/isa/inst/Zaamo/amoswap.d.aqrl.yaml b/spec/std/isa/inst/Zaamo/amoswap.d.aqrl.yaml new file mode 100644 index 0000000000..16f8c43954 --- /dev/null +++ b/spec/std/isa/inst/Zaamo/amoswap.d.aqrl.yaml @@ -0,0 +1,141 @@ +# Copyright (c) Qualcomm Technologies, Inc. and/or its subsidiaries. + +# WARNING: This file is auto-generated from spec/std/isa/inst/Zaamo/amoswap.SIZE.AQRL.layout# Copyright (c) Abhijit Das(Sukuna0007Abhi) +# SPDX-License-Identifier: BSD-3-Clause-Clear + +# yaml-language-server: $schema=../../../../schemas/inst_schema.json + +$schema: "inst_schema.json#" +kind: instruction +name: amoswap.d.aqrl +long_name: Atomic SWAP doubleword (acquire-release) +description: | + Atomically with acquire and release ordering: + + * Load the doubleword at address _xs1_ + * Write the loaded value into _xd_ + * Store the value of register _xs2_ to the address in _xs1_ +definedBy: Zaamo +base: 64 +assembly: xd, xs2, (xs1) +encoding: + match: 0000111----------011-----0101111 + variables: + - name: xs2 + location: 24-20 + - name: xs1 + location: 19-15 + - name: xd + location: 11-7 +access: + s: always + u: always + vs: always + vu: always +operation(): | + if (!implemented?(ExtensionName::A) || (MISA_CSR_IMPLEMENTED && (CSR[misa].A == 1'b0))) { + raise (ExceptionCode::IllegalInstruction, mode(), $encoding); + } + + memory_model_acquire(); + + XReg virtual_address = X[xs1]; + X[xd] = amo<64>(virtual_address, X[xs2], AmoOperation::Swap, 1'b1, 1'b1, $encoding); + + memory_model_release(); + +# SPDX-SnippetBegin +# SPDX-FileCopyrightText: 2017-2025 Contributors to the RISCV Sail Model +# SPDX-License-Identifier: BSD-2-Clause +sail(): | + { + if extension("A") then { + /* Get the address, X(rs1) (no offset). + * Some extensions perform additional checks on address validity. + */ + match ext_data_get_addr(rs1, zeros(), ReadWrite(Data, Data), width) { + Ext_DataAddr_Error(e) => { ext_handle_data_check_error(e); RETIRE_FAIL }, + Ext_DataAddr_OK(vaddr) => { + match translateAddr(vaddr, ReadWrite(Data, Data)) { + TR_Failure(e, _) => { handle_mem_exception(vaddr, e); RETIRE_FAIL }, + TR_Address(addr, _) => { + let eares : MemoryOpResult(unit) = match (width, sizeof(xlen)) { + (BYTE, _) => mem_write_ea(addr, 1, aq & rl, rl, true), + (HALF, _) => mem_write_ea(addr, 2, aq & rl, rl, true), + (WORD, _) => mem_write_ea(addr, 4, aq & rl, rl, true), + (DOUBLE, 64) => mem_write_ea(addr, 8, aq & rl, rl, true), + _ => internal_error(__FILE__, __LINE__, "Unexpected AMO width") + }; + let is_unsigned : bool = match op { + AMOMINU => true, + AMOMAXU => true, + _ => false + }; + let rs2_val : xlenbits = match width { + BYTE => if is_unsigned then zero_extend(X(rs2)[7..0]) else sign_extend(X(rs2)[7..0]), + HALF => if is_unsigned then zero_extend(X(rs2)[15..0]) else sign_extend(X(rs2)[15..0]), + WORD => if is_unsigned then zero_extend(X(rs2)[31..0]) else sign_extend(X(rs2)[31..0]), + DOUBLE => X(rs2) + }; + match (eares) { + MemException(e) => { handle_mem_exception(vaddr, e); RETIRE_FAIL }, + MemValue(_) => { + let mval : MemoryOpResult(xlenbits) = match (width, sizeof(xlen)) { + (BYTE, _) => extend_value(is_unsigned, mem_read(ReadWrite(Data, Data), addr, 1, aq, aq & rl, true)), + (HALF, _) => extend_value(is_unsigned, mem_read(ReadWrite(Data, Data), addr, 2, aq, aq & rl, true)), + (WORD, _) => extend_value(is_unsigned, mem_read(ReadWrite(Data, Data), addr, 4, aq, aq & rl, true)), + (DOUBLE, 64) => extend_value(is_unsigned, mem_read(ReadWrite(Data, Data), addr, 8, aq, aq & rl, true)), + _ => internal_error(__FILE__, __LINE__, "Unexpected AMO width") + }; + match (mval) { + MemException(e) => { handle_mem_exception(vaddr, e); RETIRE_FAIL }, + MemValue(loaded) => { + let result : xlenbits = + match op { + AMOSWAP => rs2_val, + AMOADD => rs2_val + loaded, + AMOXOR => rs2_val ^ loaded, + AMOAND => rs2_val & loaded, + AMOOR => rs2_val | loaded, + + /* These operations convert bitvectors to integer values using [un]signed, + * and back using to_bits(). + */ + AMOMIN => to_bits(sizeof(xlen), min(signed(rs2_val), signed(loaded))), + AMOMAX => to_bits(sizeof(xlen), max(signed(rs2_val), signed(loaded))), + AMOMINU => to_bits(sizeof(xlen), min(unsigned(rs2_val), unsigned(loaded))), + AMOMAXU => to_bits(sizeof(xlen), max(unsigned(rs2_val), unsigned(loaded))) + }; + let rval : xlenbits = match width { + BYTE => sign_extend(loaded[7..0]), + HALF => sign_extend(loaded[15..0]), + WORD => sign_extend(loaded[31..0]), + DOUBLE => loaded + }; + let wval : MemoryOpResult(bool) = match (width, sizeof(xlen)) { + (BYTE, _) => mem_write_value(addr, 1, result[7..0], aq & rl, rl, true), + (HALF, _) => mem_write_value(addr, 2, result[15..0], aq & rl, rl, true), + (WORD, _) => mem_write_value(addr, 4, result[31..0], aq & rl, rl, true), + (DOUBLE, 64) => mem_write_value(addr, 8, result, aq & rl, rl, true), + _ => internal_error(__FILE__, __LINE__, "Unexpected AMO width") + }; + match (wval) { + MemValue(true) => { X(rd) = rval; RETIRE_SUCCESS }, + MemValue(false) => { internal_error(__FILE__, __LINE__, "AMO got false from mem_write_value") }, + MemException(e) => { handle_mem_exception(vaddr, e); RETIRE_FAIL } + } + } + } + } + } + } + } + } + } + } else { + handle_illegal(); + RETIRE_FAIL + } + } + +# SPDX-SnippetEnd diff --git a/spec/std/isa/inst/Zaamo/amoswap.d.rl.yaml b/spec/std/isa/inst/Zaamo/amoswap.d.rl.yaml new file mode 100644 index 0000000000..2b2985387f --- /dev/null +++ b/spec/std/isa/inst/Zaamo/amoswap.d.rl.yaml @@ -0,0 +1,139 @@ +# Copyright (c) Qualcomm Technologies, Inc. and/or its subsidiaries. + +# WARNING: This file is auto-generated from spec/std/isa/inst/Zaamo/amoswap.SIZE.AQRL.layout# Copyright (c) Abhijit Das(Sukuna0007Abhi) +# SPDX-License-Identifier: BSD-3-Clause-Clear + +# yaml-language-server: $schema=../../../../schemas/inst_schema.json + +$schema: "inst_schema.json#" +kind: instruction +name: amoswap.d.rl +long_name: Atomic SWAP doubleword (release) +description: | + Atomically with release ordering: + + * Load the doubleword at address _xs1_ + * Write the loaded value into _xd_ + * Store the value of register _xs2_ to the address in _xs1_ +definedBy: Zaamo +base: 64 +assembly: xd, xs2, (xs1) +encoding: + match: 0000101----------011-----0101111 + variables: + - name: xs2 + location: 24-20 + - name: xs1 + location: 19-15 + - name: xd + location: 11-7 +access: + s: always + u: always + vs: always + vu: always +operation(): | + if (!implemented?(ExtensionName::A) || (MISA_CSR_IMPLEMENTED && (CSR[misa].A == 1'b0))) { + raise (ExceptionCode::IllegalInstruction, mode(), $encoding); + } + + XReg virtual_address = X[xs1]; + X[xd] = amo<64>(virtual_address, X[xs2], AmoOperation::Swap, 1'b0, 1'b1, $encoding); + + memory_model_release(); + +# SPDX-SnippetBegin +# SPDX-FileCopyrightText: 2017-2025 Contributors to the RISCV Sail Model +# SPDX-License-Identifier: BSD-2-Clause +sail(): | + { + if extension("A") then { + /* Get the address, X(rs1) (no offset). + * Some extensions perform additional checks on address validity. + */ + match ext_data_get_addr(rs1, zeros(), ReadWrite(Data, Data), width) { + Ext_DataAddr_Error(e) => { ext_handle_data_check_error(e); RETIRE_FAIL }, + Ext_DataAddr_OK(vaddr) => { + match translateAddr(vaddr, ReadWrite(Data, Data)) { + TR_Failure(e, _) => { handle_mem_exception(vaddr, e); RETIRE_FAIL }, + TR_Address(addr, _) => { + let eares : MemoryOpResult(unit) = match (width, sizeof(xlen)) { + (BYTE, _) => mem_write_ea(addr, 1, aq & rl, rl, true), + (HALF, _) => mem_write_ea(addr, 2, aq & rl, rl, true), + (WORD, _) => mem_write_ea(addr, 4, aq & rl, rl, true), + (DOUBLE, 64) => mem_write_ea(addr, 8, aq & rl, rl, true), + _ => internal_error(__FILE__, __LINE__, "Unexpected AMO width") + }; + let is_unsigned : bool = match op { + AMOMINU => true, + AMOMAXU => true, + _ => false + }; + let rs2_val : xlenbits = match width { + BYTE => if is_unsigned then zero_extend(X(rs2)[7..0]) else sign_extend(X(rs2)[7..0]), + HALF => if is_unsigned then zero_extend(X(rs2)[15..0]) else sign_extend(X(rs2)[15..0]), + WORD => if is_unsigned then zero_extend(X(rs2)[31..0]) else sign_extend(X(rs2)[31..0]), + DOUBLE => X(rs2) + }; + match (eares) { + MemException(e) => { handle_mem_exception(vaddr, e); RETIRE_FAIL }, + MemValue(_) => { + let mval : MemoryOpResult(xlenbits) = match (width, sizeof(xlen)) { + (BYTE, _) => extend_value(is_unsigned, mem_read(ReadWrite(Data, Data), addr, 1, aq, aq & rl, true)), + (HALF, _) => extend_value(is_unsigned, mem_read(ReadWrite(Data, Data), addr, 2, aq, aq & rl, true)), + (WORD, _) => extend_value(is_unsigned, mem_read(ReadWrite(Data, Data), addr, 4, aq, aq & rl, true)), + (DOUBLE, 64) => extend_value(is_unsigned, mem_read(ReadWrite(Data, Data), addr, 8, aq, aq & rl, true)), + _ => internal_error(__FILE__, __LINE__, "Unexpected AMO width") + }; + match (mval) { + MemException(e) => { handle_mem_exception(vaddr, e); RETIRE_FAIL }, + MemValue(loaded) => { + let result : xlenbits = + match op { + AMOSWAP => rs2_val, + AMOADD => rs2_val + loaded, + AMOXOR => rs2_val ^ loaded, + AMOAND => rs2_val & loaded, + AMOOR => rs2_val | loaded, + + /* These operations convert bitvectors to integer values using [un]signed, + * and back using to_bits(). + */ + AMOMIN => to_bits(sizeof(xlen), min(signed(rs2_val), signed(loaded))), + AMOMAX => to_bits(sizeof(xlen), max(signed(rs2_val), signed(loaded))), + AMOMINU => to_bits(sizeof(xlen), min(unsigned(rs2_val), unsigned(loaded))), + AMOMAXU => to_bits(sizeof(xlen), max(unsigned(rs2_val), unsigned(loaded))) + }; + let rval : xlenbits = match width { + BYTE => sign_extend(loaded[7..0]), + HALF => sign_extend(loaded[15..0]), + WORD => sign_extend(loaded[31..0]), + DOUBLE => loaded + }; + let wval : MemoryOpResult(bool) = match (width, sizeof(xlen)) { + (BYTE, _) => mem_write_value(addr, 1, result[7..0], aq & rl, rl, true), + (HALF, _) => mem_write_value(addr, 2, result[15..0], aq & rl, rl, true), + (WORD, _) => mem_write_value(addr, 4, result[31..0], aq & rl, rl, true), + (DOUBLE, 64) => mem_write_value(addr, 8, result, aq & rl, rl, true), + _ => internal_error(__FILE__, __LINE__, "Unexpected AMO width") + }; + match (wval) { + MemValue(true) => { X(rd) = rval; RETIRE_SUCCESS }, + MemValue(false) => { internal_error(__FILE__, __LINE__, "AMO got false from mem_write_value") }, + MemException(e) => { handle_mem_exception(vaddr, e); RETIRE_FAIL } + } + } + } + } + } + } + } + } + } + } else { + handle_illegal(); + RETIRE_FAIL + } + } + +# SPDX-SnippetEnd diff --git a/spec/std/isa/inst/Zaamo/amoswap.d.yaml b/spec/std/isa/inst/Zaamo/amoswap.d.yaml index 8105c3d6c0..b3ea2861dd 100644 --- a/spec/std/isa/inst/Zaamo/amoswap.d.yaml +++ b/spec/std/isa/inst/Zaamo/amoswap.d.yaml @@ -1,4 +1,6 @@ # Copyright (c) Qualcomm Technologies, Inc. and/or its subsidiaries. + +# WARNING: This file is auto-generated from spec/std/isa/inst/Zaamo/amoswap.SIZE.AQRL.layout# Copyright (c) Abhijit Das(Sukuna0007Abhi) # SPDX-License-Identifier: BSD-3-Clause-Clear # yaml-language-server: $schema=../../../../schemas/inst_schema.json @@ -11,18 +13,14 @@ description: | Atomically: * Load the doubleword at address _xs1_ - * Write the value into _xd_ + * Write the loaded value into _xd_ * Store the value of register _xs2_ to the address in _xs1_ definedBy: Zaamo base: 64 assembly: xd, xs2, (xs1) encoding: - match: 00001------------011-----0101111 + match: 0000100----------011-----0101111 variables: - - name: aq - location: 26 - - name: rl - location: 25 - name: xs2 location: 24-20 - name: xs1 @@ -35,15 +33,12 @@ access: vs: always vu: always operation(): | - if (implemented?(ExtensionName::A) && (CSR[misa].A == 1'b0)) { - # even though this is a memory operation, the exception occurs before that would be known, - # so mode() is the correct reporting mode rathat than effective_ldst_mode() + if (!implemented?(ExtensionName::A) || (MISA_CSR_IMPLEMENTED && (CSR[misa].A == 1'b0))) { raise (ExceptionCode::IllegalInstruction, mode(), $encoding); } XReg virtual_address = X[xs1]; - - X[xd] = amo<64>(virtual_address, X[xs2], AmoOperation::Swap, aq, rl, $encoding); + X[xd] = amo<64>(virtual_address, X[xs2], AmoOperation::Swap, 1'b0, 1'b0, $encoding); # SPDX-SnippetBegin # SPDX-FileCopyrightText: 2017-2025 Contributors to the RISCV Sail Model diff --git a/spec/std/isa/inst/Zaamo/amoswap.w.aq.yaml b/spec/std/isa/inst/Zaamo/amoswap.w.aq.yaml new file mode 100644 index 0000000000..19d2f139aa --- /dev/null +++ b/spec/std/isa/inst/Zaamo/amoswap.w.aq.yaml @@ -0,0 +1,138 @@ +# Copyright (c) Qualcomm Technologies, Inc. and/or its subsidiaries. + +# WARNING: This file is auto-generated from spec/std/isa/inst/Zaamo/amoswap.SIZE.AQRL.layout# Copyright (c) Abhijit Das(Sukuna0007Abhi) +# SPDX-License-Identifier: BSD-3-Clause-Clear + +# yaml-language-server: $schema=../../../../schemas/inst_schema.json + +$schema: "inst_schema.json#" +kind: instruction +name: amoswap.w.aq +long_name: Atomic SWAP word (acquire) +description: | + Atomically with acquire ordering: + + * Load the word at address _xs1_ + * Write the sign-extended value into _xd_ + * Store the least-significant word of register _xs2_ to the address in _xs1_ +definedBy: Zaamo +assembly: xd, xs2, (xs1) +encoding: + match: 0000110----------010-----0101111 + variables: + - name: xs2 + location: 24-20 + - name: xs1 + location: 19-15 + - name: xd + location: 11-7 +access: + s: always + u: always + vs: always + vu: always +operation(): | + if (!implemented?(ExtensionName::A) || (MISA_CSR_IMPLEMENTED && (CSR[misa].A == 1'b0))) { + raise (ExceptionCode::IllegalInstruction, mode(), $encoding); + } + + memory_model_acquire(); + + XReg virtual_address = X[xs1]; + X[xd] = amo<32>(virtual_address, X[xs2][31:0], AmoOperation::Swap, 1'b1, 1'b0, $encoding); + +# SPDX-SnippetBegin +# SPDX-FileCopyrightText: 2017-2025 Contributors to the RISCV Sail Model +# SPDX-License-Identifier: BSD-2-Clause +sail(): | + { + if extension("A") then { + /* Get the address, X(rs1) (no offset). + * Some extensions perform additional checks on address validity. + */ + match ext_data_get_addr(rs1, zeros(), ReadWrite(Data, Data), width) { + Ext_DataAddr_Error(e) => { ext_handle_data_check_error(e); RETIRE_FAIL }, + Ext_DataAddr_OK(vaddr) => { + match translateAddr(vaddr, ReadWrite(Data, Data)) { + TR_Failure(e, _) => { handle_mem_exception(vaddr, e); RETIRE_FAIL }, + TR_Address(addr, _) => { + let eares : MemoryOpResult(unit) = match (width, sizeof(xlen)) { + (BYTE, _) => mem_write_ea(addr, 1, aq & rl, rl, true), + (HALF, _) => mem_write_ea(addr, 2, aq & rl, rl, true), + (WORD, _) => mem_write_ea(addr, 4, aq & rl, rl, true), + (DOUBLE, 64) => mem_write_ea(addr, 8, aq & rl, rl, true), + _ => internal_error(__FILE__, __LINE__, "Unexpected AMO width") + }; + let is_unsigned : bool = match op { + AMOMINU => true, + AMOMAXU => true, + _ => false + }; + let rs2_val : xlenbits = match width { + BYTE => if is_unsigned then zero_extend(X(rs2)[7..0]) else sign_extend(X(rs2)[7..0]), + HALF => if is_unsigned then zero_extend(X(rs2)[15..0]) else sign_extend(X(rs2)[15..0]), + WORD => if is_unsigned then zero_extend(X(rs2)[31..0]) else sign_extend(X(rs2)[31..0]), + DOUBLE => X(rs2) + }; + match (eares) { + MemException(e) => { handle_mem_exception(vaddr, e); RETIRE_FAIL }, + MemValue(_) => { + let mval : MemoryOpResult(xlenbits) = match (width, sizeof(xlen)) { + (BYTE, _) => extend_value(is_unsigned, mem_read(ReadWrite(Data, Data), addr, 1, aq, aq & rl, true)), + (HALF, _) => extend_value(is_unsigned, mem_read(ReadWrite(Data, Data), addr, 2, aq, aq & rl, true)), + (WORD, _) => extend_value(is_unsigned, mem_read(ReadWrite(Data, Data), addr, 4, aq, aq & rl, true)), + (DOUBLE, 64) => extend_value(is_unsigned, mem_read(ReadWrite(Data, Data), addr, 8, aq, aq & rl, true)), + _ => internal_error(__FILE__, __LINE__, "Unexpected AMO width") + }; + match (mval) { + MemException(e) => { handle_mem_exception(vaddr, e); RETIRE_FAIL }, + MemValue(loaded) => { + let result : xlenbits = + match op { + AMOSWAP => rs2_val, + AMOADD => rs2_val + loaded, + AMOXOR => rs2_val ^ loaded, + AMOAND => rs2_val & loaded, + AMOOR => rs2_val | loaded, + + /* These operations convert bitvectors to integer values using [un]signed, + * and back using to_bits(). + */ + AMOMIN => to_bits(sizeof(xlen), min(signed(rs2_val), signed(loaded))), + AMOMAX => to_bits(sizeof(xlen), max(signed(rs2_val), signed(loaded))), + AMOMINU => to_bits(sizeof(xlen), min(unsigned(rs2_val), unsigned(loaded))), + AMOMAXU => to_bits(sizeof(xlen), max(unsigned(rs2_val), unsigned(loaded))) + }; + let rval : xlenbits = match width { + BYTE => sign_extend(loaded[7..0]), + HALF => sign_extend(loaded[15..0]), + WORD => sign_extend(loaded[31..0]), + DOUBLE => loaded + }; + let wval : MemoryOpResult(bool) = match (width, sizeof(xlen)) { + (BYTE, _) => mem_write_value(addr, 1, result[7..0], aq & rl, rl, true), + (HALF, _) => mem_write_value(addr, 2, result[15..0], aq & rl, rl, true), + (WORD, _) => mem_write_value(addr, 4, result[31..0], aq & rl, rl, true), + (DOUBLE, 64) => mem_write_value(addr, 8, result, aq & rl, rl, true), + _ => internal_error(__FILE__, __LINE__, "Unexpected AMO width") + }; + match (wval) { + MemValue(true) => { X(rd) = rval; RETIRE_SUCCESS }, + MemValue(false) => { internal_error(__FILE__, __LINE__, "AMO got false from mem_write_value") }, + MemException(e) => { handle_mem_exception(vaddr, e); RETIRE_FAIL } + } + } + } + } + } + } + } + } + } + } else { + handle_illegal(); + RETIRE_FAIL + } + } + +# SPDX-SnippetEnd diff --git a/spec/std/isa/inst/Zaamo/amoswap.w.aqrl.yaml b/spec/std/isa/inst/Zaamo/amoswap.w.aqrl.yaml new file mode 100644 index 0000000000..c36888bab0 --- /dev/null +++ b/spec/std/isa/inst/Zaamo/amoswap.w.aqrl.yaml @@ -0,0 +1,140 @@ +# Copyright (c) Qualcomm Technologies, Inc. and/or its subsidiaries. + +# WARNING: This file is auto-generated from spec/std/isa/inst/Zaamo/amoswap.SIZE.AQRL.layout# Copyright (c) Abhijit Das(Sukuna0007Abhi) +# SPDX-License-Identifier: BSD-3-Clause-Clear + +# yaml-language-server: $schema=../../../../schemas/inst_schema.json + +$schema: "inst_schema.json#" +kind: instruction +name: amoswap.w.aqrl +long_name: Atomic SWAP word (acquire-release) +description: | + Atomically with acquire and release ordering: + + * Load the word at address _xs1_ + * Write the sign-extended value into _xd_ + * Store the least-significant word of register _xs2_ to the address in _xs1_ +definedBy: Zaamo +assembly: xd, xs2, (xs1) +encoding: + match: 0000111----------010-----0101111 + variables: + - name: xs2 + location: 24-20 + - name: xs1 + location: 19-15 + - name: xd + location: 11-7 +access: + s: always + u: always + vs: always + vu: always +operation(): | + if (!implemented?(ExtensionName::A) || (MISA_CSR_IMPLEMENTED && (CSR[misa].A == 1'b0))) { + raise (ExceptionCode::IllegalInstruction, mode(), $encoding); + } + + memory_model_acquire(); + + XReg virtual_address = X[xs1]; + X[xd] = amo<32>(virtual_address, X[xs2][31:0], AmoOperation::Swap, 1'b1, 1'b1, $encoding); + + memory_model_release(); + +# SPDX-SnippetBegin +# SPDX-FileCopyrightText: 2017-2025 Contributors to the RISCV Sail Model +# SPDX-License-Identifier: BSD-2-Clause +sail(): | + { + if extension("A") then { + /* Get the address, X(rs1) (no offset). + * Some extensions perform additional checks on address validity. + */ + match ext_data_get_addr(rs1, zeros(), ReadWrite(Data, Data), width) { + Ext_DataAddr_Error(e) => { ext_handle_data_check_error(e); RETIRE_FAIL }, + Ext_DataAddr_OK(vaddr) => { + match translateAddr(vaddr, ReadWrite(Data, Data)) { + TR_Failure(e, _) => { handle_mem_exception(vaddr, e); RETIRE_FAIL }, + TR_Address(addr, _) => { + let eares : MemoryOpResult(unit) = match (width, sizeof(xlen)) { + (BYTE, _) => mem_write_ea(addr, 1, aq & rl, rl, true), + (HALF, _) => mem_write_ea(addr, 2, aq & rl, rl, true), + (WORD, _) => mem_write_ea(addr, 4, aq & rl, rl, true), + (DOUBLE, 64) => mem_write_ea(addr, 8, aq & rl, rl, true), + _ => internal_error(__FILE__, __LINE__, "Unexpected AMO width") + }; + let is_unsigned : bool = match op { + AMOMINU => true, + AMOMAXU => true, + _ => false + }; + let rs2_val : xlenbits = match width { + BYTE => if is_unsigned then zero_extend(X(rs2)[7..0]) else sign_extend(X(rs2)[7..0]), + HALF => if is_unsigned then zero_extend(X(rs2)[15..0]) else sign_extend(X(rs2)[15..0]), + WORD => if is_unsigned then zero_extend(X(rs2)[31..0]) else sign_extend(X(rs2)[31..0]), + DOUBLE => X(rs2) + }; + match (eares) { + MemException(e) => { handle_mem_exception(vaddr, e); RETIRE_FAIL }, + MemValue(_) => { + let mval : MemoryOpResult(xlenbits) = match (width, sizeof(xlen)) { + (BYTE, _) => extend_value(is_unsigned, mem_read(ReadWrite(Data, Data), addr, 1, aq, aq & rl, true)), + (HALF, _) => extend_value(is_unsigned, mem_read(ReadWrite(Data, Data), addr, 2, aq, aq & rl, true)), + (WORD, _) => extend_value(is_unsigned, mem_read(ReadWrite(Data, Data), addr, 4, aq, aq & rl, true)), + (DOUBLE, 64) => extend_value(is_unsigned, mem_read(ReadWrite(Data, Data), addr, 8, aq, aq & rl, true)), + _ => internal_error(__FILE__, __LINE__, "Unexpected AMO width") + }; + match (mval) { + MemException(e) => { handle_mem_exception(vaddr, e); RETIRE_FAIL }, + MemValue(loaded) => { + let result : xlenbits = + match op { + AMOSWAP => rs2_val, + AMOADD => rs2_val + loaded, + AMOXOR => rs2_val ^ loaded, + AMOAND => rs2_val & loaded, + AMOOR => rs2_val | loaded, + + /* These operations convert bitvectors to integer values using [un]signed, + * and back using to_bits(). + */ + AMOMIN => to_bits(sizeof(xlen), min(signed(rs2_val), signed(loaded))), + AMOMAX => to_bits(sizeof(xlen), max(signed(rs2_val), signed(loaded))), + AMOMINU => to_bits(sizeof(xlen), min(unsigned(rs2_val), unsigned(loaded))), + AMOMAXU => to_bits(sizeof(xlen), max(unsigned(rs2_val), unsigned(loaded))) + }; + let rval : xlenbits = match width { + BYTE => sign_extend(loaded[7..0]), + HALF => sign_extend(loaded[15..0]), + WORD => sign_extend(loaded[31..0]), + DOUBLE => loaded + }; + let wval : MemoryOpResult(bool) = match (width, sizeof(xlen)) { + (BYTE, _) => mem_write_value(addr, 1, result[7..0], aq & rl, rl, true), + (HALF, _) => mem_write_value(addr, 2, result[15..0], aq & rl, rl, true), + (WORD, _) => mem_write_value(addr, 4, result[31..0], aq & rl, rl, true), + (DOUBLE, 64) => mem_write_value(addr, 8, result, aq & rl, rl, true), + _ => internal_error(__FILE__, __LINE__, "Unexpected AMO width") + }; + match (wval) { + MemValue(true) => { X(rd) = rval; RETIRE_SUCCESS }, + MemValue(false) => { internal_error(__FILE__, __LINE__, "AMO got false from mem_write_value") }, + MemException(e) => { handle_mem_exception(vaddr, e); RETIRE_FAIL } + } + } + } + } + } + } + } + } + } + } else { + handle_illegal(); + RETIRE_FAIL + } + } + +# SPDX-SnippetEnd diff --git a/spec/std/isa/inst/Zaamo/amoswap.w.rl.yaml b/spec/std/isa/inst/Zaamo/amoswap.w.rl.yaml new file mode 100644 index 0000000000..8a8c9d66ab --- /dev/null +++ b/spec/std/isa/inst/Zaamo/amoswap.w.rl.yaml @@ -0,0 +1,138 @@ +# Copyright (c) Qualcomm Technologies, Inc. and/or its subsidiaries. + +# WARNING: This file is auto-generated from spec/std/isa/inst/Zaamo/amoswap.SIZE.AQRL.layout# Copyright (c) Abhijit Das(Sukuna0007Abhi) +# SPDX-License-Identifier: BSD-3-Clause-Clear + +# yaml-language-server: $schema=../../../../schemas/inst_schema.json + +$schema: "inst_schema.json#" +kind: instruction +name: amoswap.w.rl +long_name: Atomic SWAP word (release) +description: | + Atomically with release ordering: + + * Load the word at address _xs1_ + * Write the sign-extended value into _xd_ + * Store the least-significant word of register _xs2_ to the address in _xs1_ +definedBy: Zaamo +assembly: xd, xs2, (xs1) +encoding: + match: 0000101----------010-----0101111 + variables: + - name: xs2 + location: 24-20 + - name: xs1 + location: 19-15 + - name: xd + location: 11-7 +access: + s: always + u: always + vs: always + vu: always +operation(): | + if (!implemented?(ExtensionName::A) || (MISA_CSR_IMPLEMENTED && (CSR[misa].A == 1'b0))) { + raise (ExceptionCode::IllegalInstruction, mode(), $encoding); + } + + XReg virtual_address = X[xs1]; + X[xd] = amo<32>(virtual_address, X[xs2][31:0], AmoOperation::Swap, 1'b0, 1'b1, $encoding); + + memory_model_release(); + +# SPDX-SnippetBegin +# SPDX-FileCopyrightText: 2017-2025 Contributors to the RISCV Sail Model +# SPDX-License-Identifier: BSD-2-Clause +sail(): | + { + if extension("A") then { + /* Get the address, X(rs1) (no offset). + * Some extensions perform additional checks on address validity. + */ + match ext_data_get_addr(rs1, zeros(), ReadWrite(Data, Data), width) { + Ext_DataAddr_Error(e) => { ext_handle_data_check_error(e); RETIRE_FAIL }, + Ext_DataAddr_OK(vaddr) => { + match translateAddr(vaddr, ReadWrite(Data, Data)) { + TR_Failure(e, _) => { handle_mem_exception(vaddr, e); RETIRE_FAIL }, + TR_Address(addr, _) => { + let eares : MemoryOpResult(unit) = match (width, sizeof(xlen)) { + (BYTE, _) => mem_write_ea(addr, 1, aq & rl, rl, true), + (HALF, _) => mem_write_ea(addr, 2, aq & rl, rl, true), + (WORD, _) => mem_write_ea(addr, 4, aq & rl, rl, true), + (DOUBLE, 64) => mem_write_ea(addr, 8, aq & rl, rl, true), + _ => internal_error(__FILE__, __LINE__, "Unexpected AMO width") + }; + let is_unsigned : bool = match op { + AMOMINU => true, + AMOMAXU => true, + _ => false + }; + let rs2_val : xlenbits = match width { + BYTE => if is_unsigned then zero_extend(X(rs2)[7..0]) else sign_extend(X(rs2)[7..0]), + HALF => if is_unsigned then zero_extend(X(rs2)[15..0]) else sign_extend(X(rs2)[15..0]), + WORD => if is_unsigned then zero_extend(X(rs2)[31..0]) else sign_extend(X(rs2)[31..0]), + DOUBLE => X(rs2) + }; + match (eares) { + MemException(e) => { handle_mem_exception(vaddr, e); RETIRE_FAIL }, + MemValue(_) => { + let mval : MemoryOpResult(xlenbits) = match (width, sizeof(xlen)) { + (BYTE, _) => extend_value(is_unsigned, mem_read(ReadWrite(Data, Data), addr, 1, aq, aq & rl, true)), + (HALF, _) => extend_value(is_unsigned, mem_read(ReadWrite(Data, Data), addr, 2, aq, aq & rl, true)), + (WORD, _) => extend_value(is_unsigned, mem_read(ReadWrite(Data, Data), addr, 4, aq, aq & rl, true)), + (DOUBLE, 64) => extend_value(is_unsigned, mem_read(ReadWrite(Data, Data), addr, 8, aq, aq & rl, true)), + _ => internal_error(__FILE__, __LINE__, "Unexpected AMO width") + }; + match (mval) { + MemException(e) => { handle_mem_exception(vaddr, e); RETIRE_FAIL }, + MemValue(loaded) => { + let result : xlenbits = + match op { + AMOSWAP => rs2_val, + AMOADD => rs2_val + loaded, + AMOXOR => rs2_val ^ loaded, + AMOAND => rs2_val & loaded, + AMOOR => rs2_val | loaded, + + /* These operations convert bitvectors to integer values using [un]signed, + * and back using to_bits(). + */ + AMOMIN => to_bits(sizeof(xlen), min(signed(rs2_val), signed(loaded))), + AMOMAX => to_bits(sizeof(xlen), max(signed(rs2_val), signed(loaded))), + AMOMINU => to_bits(sizeof(xlen), min(unsigned(rs2_val), unsigned(loaded))), + AMOMAXU => to_bits(sizeof(xlen), max(unsigned(rs2_val), unsigned(loaded))) + }; + let rval : xlenbits = match width { + BYTE => sign_extend(loaded[7..0]), + HALF => sign_extend(loaded[15..0]), + WORD => sign_extend(loaded[31..0]), + DOUBLE => loaded + }; + let wval : MemoryOpResult(bool) = match (width, sizeof(xlen)) { + (BYTE, _) => mem_write_value(addr, 1, result[7..0], aq & rl, rl, true), + (HALF, _) => mem_write_value(addr, 2, result[15..0], aq & rl, rl, true), + (WORD, _) => mem_write_value(addr, 4, result[31..0], aq & rl, rl, true), + (DOUBLE, 64) => mem_write_value(addr, 8, result, aq & rl, rl, true), + _ => internal_error(__FILE__, __LINE__, "Unexpected AMO width") + }; + match (wval) { + MemValue(true) => { X(rd) = rval; RETIRE_SUCCESS }, + MemValue(false) => { internal_error(__FILE__, __LINE__, "AMO got false from mem_write_value") }, + MemException(e) => { handle_mem_exception(vaddr, e); RETIRE_FAIL } + } + } + } + } + } + } + } + } + } + } else { + handle_illegal(); + RETIRE_FAIL + } + } + +# SPDX-SnippetEnd diff --git a/spec/std/isa/inst/Zaamo/amoswap.w.yaml b/spec/std/isa/inst/Zaamo/amoswap.w.yaml index 2e4e5ea971..0cd13d295a 100644 --- a/spec/std/isa/inst/Zaamo/amoswap.w.yaml +++ b/spec/std/isa/inst/Zaamo/amoswap.w.yaml @@ -1,4 +1,6 @@ # Copyright (c) Qualcomm Technologies, Inc. and/or its subsidiaries. + +# WARNING: This file is auto-generated from spec/std/isa/inst/Zaamo/amoswap.SIZE.AQRL.layout# Copyright (c) Abhijit Das(Sukuna0007Abhi) # SPDX-License-Identifier: BSD-3-Clause-Clear # yaml-language-server: $schema=../../../../schemas/inst_schema.json @@ -16,12 +18,8 @@ description: | definedBy: Zaamo assembly: xd, xs2, (xs1) encoding: - match: 00001------------010-----0101111 + match: 0000100----------010-----0101111 variables: - - name: aq - location: 26 - - name: rl - location: 25 - name: xs2 location: 24-20 - name: xs1 @@ -34,15 +32,12 @@ access: vs: always vu: always operation(): | - if (implemented?(ExtensionName::A) && (CSR[misa].A == 1'b0)) { - # even though this is a memory operation, the exception occurs before that would be known, - # so mode() is the correct reporting mode rathat than effective_ldst_mode() + if (!implemented?(ExtensionName::A) || (MISA_CSR_IMPLEMENTED && (CSR[misa].A == 1'b0))) { raise (ExceptionCode::IllegalInstruction, mode(), $encoding); } XReg virtual_address = X[xs1]; - - X[xd] = amo<32>(virtual_address, X[xs2][31:0], AmoOperation::Swap, aq, rl, $encoding); + X[xd] = amo<32>(virtual_address, X[xs2][31:0], AmoOperation::Swap, 1'b0, 1'b0, $encoding); # SPDX-SnippetBegin # SPDX-FileCopyrightText: 2017-2025 Contributors to the RISCV Sail Model diff --git a/spec/std/isa/inst/Zaamo/amoxor.SIZE.AQRL.layout b/spec/std/isa/inst/Zaamo/amoxor.SIZE.AQRL.layout new file mode 100644 index 0000000000..420416f568 --- /dev/null +++ b/spec/std/isa/inst/Zaamo/amoxor.SIZE.AQRL.layout @@ -0,0 +1,175 @@ +# Copyright (c) Qualcomm Technologies, Inc. and/or its subsidiaries. +# Copyright (c) Abhijit Das(Sukuna0007Abhi) +# SPDX-License-Identifier: BSD-3-Clause-Clear + +# yaml-language-server: $schema=../../../../schemas/inst_schema.json +<%- + raise "'size' must be defined as 'b', 'h', 'w', or 'd'" unless %w[b h w d].include?(size) + raise "'aq' must be defined as true or false" unless [true, false].include?(aq) + raise "'rl' must be defined as true or false" unless [true, false].include?(rl) + + size_info = { + "b" => { name: "byte", bits: 8, funct3: "000", operation_bits: "8" }, + "h" => { name: "halfword", bits: 16, funct3: "001", operation_bits: "16" }, + "w" => { name: "word", bits: 32, funct3: "010", operation_bits: "32" }, + "d" => { name: "doubleword", bits: 64, funct3: "011", operation_bits: "64" } + } + + current_size = size_info[size] + + # Generate instruction name suffix based on aq/rl + aq_rl_suffix = "" + if aq && rl + aq_rl_suffix = ".aqrl" + elsif aq + aq_rl_suffix = ".aq" + elsif rl + aq_rl_suffix = ".rl" + end + + # Generate match string with fixed aq/rl bits + aq_bit = aq ? "1" : "0" + rl_bit = rl ? "1" : "0" +-%> + +$schema: "inst_schema.json#" +kind: instruction +name: amoxor.<%= size %><%= aq_rl_suffix %> +long_name: Atomic fetch-and-xor <%= current_size[:name] %><%= aq && rl ? " (acquire-release)" : (aq ? " (acquire)" : (rl ? " (release)" : "")) %> +description: | + Atomically<%= aq && rl ? " with acquire and release ordering" : (aq ? " with acquire ordering" : (rl ? " with release ordering" : "")) %>: + + * Load the <%= current_size[:name] %> at address _xs1_ + * Write the <%= %w[b h w].include?(size) ? "sign-extended value" : "loaded value" %> into _xd_ + * XOR the <%= %w[b h w].include?(size) ? "least-significant #{current_size[:name]} of register" : "value of register" %> _xs2_ to the loaded value + * Write the result to the address in _xs1_ +definedBy: <%= %w[b h].include?(size) ? "Zabha" : "Zaamo" %> +<%- if size == "d" -%> +base: 64 +<%- end -%> +assembly: xd, xs2, (xs1) +encoding: + match: 00100<%= aq_bit %><%= rl_bit %>----------<%= current_size[:funct3] %>-----0101111 + variables: + - name: xs2 + location: 24-20 + - name: xs1 + location: 19-15 + - name: xd + location: 11-7 +access: + s: always + u: always + vs: always + vu: always +operation(): | + if (!implemented?(ExtensionName::A) || (MISA_CSR_IMPLEMENTED && (CSR[misa].A == 1'b0))) { + raise (ExceptionCode::IllegalInstruction, mode(), $encoding); + } + +<% if aq -%> + memory_model_acquire(); + +<% end -%> + XReg virtual_address = X[xs1]; + X[xd] = amo<<%= current_size[:operation_bits] %>>(virtual_address, X[xs2]<%= %w[b h w].include?(size) ? "[#{current_size[:bits]-1}:0]" : "" %>, AmoOperation::Xor, <%= aq ? "1'b1" : "1'b0" %>, <%= rl ? "1'b1" : "1'b0" %>, $encoding); +<% if rl -%> + + memory_model_release(); +<% end -%> + +# SPDX-SnippetBegin +# SPDX-FileCopyrightText: 2017-2025 Contributors to the RISCV Sail Model +# SPDX-License-Identifier: BSD-2-Clause +sail(): | + { + if extension("A") then { + /* Get the address, X(rs1) (no offset). + * Some extensions perform additional checks on address validity. + */ + match ext_data_get_addr(rs1, zeros(), ReadWrite(Data, Data), width) { + Ext_DataAddr_Error(e) => { ext_handle_data_check_error(e); RETIRE_FAIL }, + Ext_DataAddr_OK(vaddr) => { + match translateAddr(vaddr, ReadWrite(Data, Data)) { + TR_Failure(e, _) => { handle_mem_exception(vaddr, e); RETIRE_FAIL }, + TR_Address(addr, _) => { + let eares : MemoryOpResult(unit) = match (width, sizeof(xlen)) { + (BYTE, _) => mem_write_ea(addr, 1, aq & rl, rl, true), + (HALF, _) => mem_write_ea(addr, 2, aq & rl, rl, true), + (WORD, _) => mem_write_ea(addr, 4, aq & rl, rl, true), + (DOUBLE, 64) => mem_write_ea(addr, 8, aq & rl, rl, true), + _ => internal_error(__FILE__, __LINE__, "Unexpected AMO width") + }; + let is_unsigned : bool = match op { + AMOMINU => true, + AMOMAXU => true, + _ => false + }; + let rs2_val : xlenbits = match width { + BYTE => if is_unsigned then zero_extend(X(rs2)[7..0]) else sign_extend(X(rs2)[7..0]), + HALF => if is_unsigned then zero_extend(X(rs2)[15..0]) else sign_extend(X(rs2)[15..0]), + WORD => if is_unsigned then zero_extend(X(rs2)[31..0]) else sign_extend(X(rs2)[31..0]), + DOUBLE => X(rs2) + }; + match (eares) { + MemException(e) => { handle_mem_exception(vaddr, e); RETIRE_FAIL }, + MemValue(_) => { + let mval : MemoryOpResult(xlenbits) = match (width, sizeof(xlen)) { + (BYTE, _) => extend_value(is_unsigned, mem_read(ReadWrite(Data, Data), addr, 1, aq, aq & rl, true)), + (HALF, _) => extend_value(is_unsigned, mem_read(ReadWrite(Data, Data), addr, 2, aq, aq & rl, true)), + (WORD, _) => extend_value(is_unsigned, mem_read(ReadWrite(Data, Data), addr, 4, aq, aq & rl, true)), + (DOUBLE, 64) => extend_value(is_unsigned, mem_read(ReadWrite(Data, Data), addr, 8, aq, aq & rl, true)), + _ => internal_error(__FILE__, __LINE__, "Unexpected AMO width") + }; + match (mval) { + MemException(e) => { handle_mem_exception(vaddr, e); RETIRE_FAIL }, + MemValue(loaded) => { + let result : xlenbits = + match op { + AMOSWAP => rs2_val, + AMOADD => rs2_val + loaded, + AMOXOR => rs2_val ^ loaded, + AMOAND => rs2_val & loaded, + AMOOR => rs2_val | loaded, + + /* These operations convert bitvectors to integer values using [un]signed, + * and back using to_bits(). + */ + AMOMIN => to_bits(sizeof(xlen), min(signed(rs2_val), signed(loaded))), + AMOMAX => to_bits(sizeof(xlen), max(signed(rs2_val), signed(loaded))), + AMOMINU => to_bits(sizeof(xlen), min(unsigned(rs2_val), unsigned(loaded))), + AMOMAXU => to_bits(sizeof(xlen), max(unsigned(rs2_val), unsigned(loaded))) + }; + let rval : xlenbits = match width { + BYTE => sign_extend(loaded[7..0]), + HALF => sign_extend(loaded[15..0]), + WORD => sign_extend(loaded[31..0]), + DOUBLE => loaded + }; + let wval : MemoryOpResult(bool) = match (width, sizeof(xlen)) { + (BYTE, _) => mem_write_value(addr, 1, result[7..0], aq & rl, rl, true), + (HALF, _) => mem_write_value(addr, 2, result[15..0], aq & rl, rl, true), + (WORD, _) => mem_write_value(addr, 4, result[31..0], aq & rl, rl, true), + (DOUBLE, 64) => mem_write_value(addr, 8, result, aq & rl, rl, true), + _ => internal_error(__FILE__, __LINE__, "Unexpected AMO width") + }; + match (wval) { + MemValue(true) => { X(rd) = rval; RETIRE_SUCCESS }, + MemValue(false) => { internal_error(__FILE__, __LINE__, "AMO got false from mem_write_value") }, + MemException(e) => { handle_mem_exception(vaddr, e); RETIRE_FAIL } + } + } + } + } + } + } + } + } + } + } else { + handle_illegal(); + RETIRE_FAIL + } + } + +# SPDX-SnippetEnd diff --git a/spec/std/isa/inst/Zaamo/amoxor.d.aq.yaml b/spec/std/isa/inst/Zaamo/amoxor.d.aq.yaml new file mode 100644 index 0000000000..f800163d04 --- /dev/null +++ b/spec/std/isa/inst/Zaamo/amoxor.d.aq.yaml @@ -0,0 +1,140 @@ +# Copyright (c) Qualcomm Technologies, Inc. and/or its subsidiaries. + +# WARNING: This file is auto-generated from spec/std/isa/inst/Zaamo/amoxor.SIZE.AQRL.layout# Copyright (c) Abhijit Das(Sukuna0007Abhi) +# SPDX-License-Identifier: BSD-3-Clause-Clear + +# yaml-language-server: $schema=../../../../schemas/inst_schema.json + +$schema: "inst_schema.json#" +kind: instruction +name: amoxor.d.aq +long_name: Atomic fetch-and-xor doubleword (acquire) +description: | + Atomically with acquire ordering: + + * Load the doubleword at address _xs1_ + * Write the loaded value into _xd_ + * XOR the value of register _xs2_ to the loaded value + * Write the result to the address in _xs1_ +definedBy: Zaamo +base: 64 +assembly: xd, xs2, (xs1) +encoding: + match: 0010010----------011-----0101111 + variables: + - name: xs2 + location: 24-20 + - name: xs1 + location: 19-15 + - name: xd + location: 11-7 +access: + s: always + u: always + vs: always + vu: always +operation(): | + if (!implemented?(ExtensionName::A) || (MISA_CSR_IMPLEMENTED && (CSR[misa].A == 1'b0))) { + raise (ExceptionCode::IllegalInstruction, mode(), $encoding); + } + + memory_model_acquire(); + + XReg virtual_address = X[xs1]; + X[xd] = amo<64>(virtual_address, X[xs2], AmoOperation::Xor, 1'b1, 1'b0, $encoding); + +# SPDX-SnippetBegin +# SPDX-FileCopyrightText: 2017-2025 Contributors to the RISCV Sail Model +# SPDX-License-Identifier: BSD-2-Clause +sail(): | + { + if extension("A") then { + /* Get the address, X(rs1) (no offset). + * Some extensions perform additional checks on address validity. + */ + match ext_data_get_addr(rs1, zeros(), ReadWrite(Data, Data), width) { + Ext_DataAddr_Error(e) => { ext_handle_data_check_error(e); RETIRE_FAIL }, + Ext_DataAddr_OK(vaddr) => { + match translateAddr(vaddr, ReadWrite(Data, Data)) { + TR_Failure(e, _) => { handle_mem_exception(vaddr, e); RETIRE_FAIL }, + TR_Address(addr, _) => { + let eares : MemoryOpResult(unit) = match (width, sizeof(xlen)) { + (BYTE, _) => mem_write_ea(addr, 1, aq & rl, rl, true), + (HALF, _) => mem_write_ea(addr, 2, aq & rl, rl, true), + (WORD, _) => mem_write_ea(addr, 4, aq & rl, rl, true), + (DOUBLE, 64) => mem_write_ea(addr, 8, aq & rl, rl, true), + _ => internal_error(__FILE__, __LINE__, "Unexpected AMO width") + }; + let is_unsigned : bool = match op { + AMOMINU => true, + AMOMAXU => true, + _ => false + }; + let rs2_val : xlenbits = match width { + BYTE => if is_unsigned then zero_extend(X(rs2)[7..0]) else sign_extend(X(rs2)[7..0]), + HALF => if is_unsigned then zero_extend(X(rs2)[15..0]) else sign_extend(X(rs2)[15..0]), + WORD => if is_unsigned then zero_extend(X(rs2)[31..0]) else sign_extend(X(rs2)[31..0]), + DOUBLE => X(rs2) + }; + match (eares) { + MemException(e) => { handle_mem_exception(vaddr, e); RETIRE_FAIL }, + MemValue(_) => { + let mval : MemoryOpResult(xlenbits) = match (width, sizeof(xlen)) { + (BYTE, _) => extend_value(is_unsigned, mem_read(ReadWrite(Data, Data), addr, 1, aq, aq & rl, true)), + (HALF, _) => extend_value(is_unsigned, mem_read(ReadWrite(Data, Data), addr, 2, aq, aq & rl, true)), + (WORD, _) => extend_value(is_unsigned, mem_read(ReadWrite(Data, Data), addr, 4, aq, aq & rl, true)), + (DOUBLE, 64) => extend_value(is_unsigned, mem_read(ReadWrite(Data, Data), addr, 8, aq, aq & rl, true)), + _ => internal_error(__FILE__, __LINE__, "Unexpected AMO width") + }; + match (mval) { + MemException(e) => { handle_mem_exception(vaddr, e); RETIRE_FAIL }, + MemValue(loaded) => { + let result : xlenbits = + match op { + AMOSWAP => rs2_val, + AMOADD => rs2_val + loaded, + AMOXOR => rs2_val ^ loaded, + AMOAND => rs2_val & loaded, + AMOOR => rs2_val | loaded, + + /* These operations convert bitvectors to integer values using [un]signed, + * and back using to_bits(). + */ + AMOMIN => to_bits(sizeof(xlen), min(signed(rs2_val), signed(loaded))), + AMOMAX => to_bits(sizeof(xlen), max(signed(rs2_val), signed(loaded))), + AMOMINU => to_bits(sizeof(xlen), min(unsigned(rs2_val), unsigned(loaded))), + AMOMAXU => to_bits(sizeof(xlen), max(unsigned(rs2_val), unsigned(loaded))) + }; + let rval : xlenbits = match width { + BYTE => sign_extend(loaded[7..0]), + HALF => sign_extend(loaded[15..0]), + WORD => sign_extend(loaded[31..0]), + DOUBLE => loaded + }; + let wval : MemoryOpResult(bool) = match (width, sizeof(xlen)) { + (BYTE, _) => mem_write_value(addr, 1, result[7..0], aq & rl, rl, true), + (HALF, _) => mem_write_value(addr, 2, result[15..0], aq & rl, rl, true), + (WORD, _) => mem_write_value(addr, 4, result[31..0], aq & rl, rl, true), + (DOUBLE, 64) => mem_write_value(addr, 8, result, aq & rl, rl, true), + _ => internal_error(__FILE__, __LINE__, "Unexpected AMO width") + }; + match (wval) { + MemValue(true) => { X(rd) = rval; RETIRE_SUCCESS }, + MemValue(false) => { internal_error(__FILE__, __LINE__, "AMO got false from mem_write_value") }, + MemException(e) => { handle_mem_exception(vaddr, e); RETIRE_FAIL } + } + } + } + } + } + } + } + } + } + } else { + handle_illegal(); + RETIRE_FAIL + } + } + +# SPDX-SnippetEnd diff --git a/spec/std/isa/inst/Zaamo/amoxor.d.aqrl.yaml b/spec/std/isa/inst/Zaamo/amoxor.d.aqrl.yaml new file mode 100644 index 0000000000..ff9e1d3a82 --- /dev/null +++ b/spec/std/isa/inst/Zaamo/amoxor.d.aqrl.yaml @@ -0,0 +1,142 @@ +# Copyright (c) Qualcomm Technologies, Inc. and/or its subsidiaries. + +# WARNING: This file is auto-generated from spec/std/isa/inst/Zaamo/amoxor.SIZE.AQRL.layout# Copyright (c) Abhijit Das(Sukuna0007Abhi) +# SPDX-License-Identifier: BSD-3-Clause-Clear + +# yaml-language-server: $schema=../../../../schemas/inst_schema.json + +$schema: "inst_schema.json#" +kind: instruction +name: amoxor.d.aqrl +long_name: Atomic fetch-and-xor doubleword (acquire-release) +description: | + Atomically with acquire and release ordering: + + * Load the doubleword at address _xs1_ + * Write the loaded value into _xd_ + * XOR the value of register _xs2_ to the loaded value + * Write the result to the address in _xs1_ +definedBy: Zaamo +base: 64 +assembly: xd, xs2, (xs1) +encoding: + match: 0010011----------011-----0101111 + variables: + - name: xs2 + location: 24-20 + - name: xs1 + location: 19-15 + - name: xd + location: 11-7 +access: + s: always + u: always + vs: always + vu: always +operation(): | + if (!implemented?(ExtensionName::A) || (MISA_CSR_IMPLEMENTED && (CSR[misa].A == 1'b0))) { + raise (ExceptionCode::IllegalInstruction, mode(), $encoding); + } + + memory_model_acquire(); + + XReg virtual_address = X[xs1]; + X[xd] = amo<64>(virtual_address, X[xs2], AmoOperation::Xor, 1'b1, 1'b1, $encoding); + + memory_model_release(); + +# SPDX-SnippetBegin +# SPDX-FileCopyrightText: 2017-2025 Contributors to the RISCV Sail Model +# SPDX-License-Identifier: BSD-2-Clause +sail(): | + { + if extension("A") then { + /* Get the address, X(rs1) (no offset). + * Some extensions perform additional checks on address validity. + */ + match ext_data_get_addr(rs1, zeros(), ReadWrite(Data, Data), width) { + Ext_DataAddr_Error(e) => { ext_handle_data_check_error(e); RETIRE_FAIL }, + Ext_DataAddr_OK(vaddr) => { + match translateAddr(vaddr, ReadWrite(Data, Data)) { + TR_Failure(e, _) => { handle_mem_exception(vaddr, e); RETIRE_FAIL }, + TR_Address(addr, _) => { + let eares : MemoryOpResult(unit) = match (width, sizeof(xlen)) { + (BYTE, _) => mem_write_ea(addr, 1, aq & rl, rl, true), + (HALF, _) => mem_write_ea(addr, 2, aq & rl, rl, true), + (WORD, _) => mem_write_ea(addr, 4, aq & rl, rl, true), + (DOUBLE, 64) => mem_write_ea(addr, 8, aq & rl, rl, true), + _ => internal_error(__FILE__, __LINE__, "Unexpected AMO width") + }; + let is_unsigned : bool = match op { + AMOMINU => true, + AMOMAXU => true, + _ => false + }; + let rs2_val : xlenbits = match width { + BYTE => if is_unsigned then zero_extend(X(rs2)[7..0]) else sign_extend(X(rs2)[7..0]), + HALF => if is_unsigned then zero_extend(X(rs2)[15..0]) else sign_extend(X(rs2)[15..0]), + WORD => if is_unsigned then zero_extend(X(rs2)[31..0]) else sign_extend(X(rs2)[31..0]), + DOUBLE => X(rs2) + }; + match (eares) { + MemException(e) => { handle_mem_exception(vaddr, e); RETIRE_FAIL }, + MemValue(_) => { + let mval : MemoryOpResult(xlenbits) = match (width, sizeof(xlen)) { + (BYTE, _) => extend_value(is_unsigned, mem_read(ReadWrite(Data, Data), addr, 1, aq, aq & rl, true)), + (HALF, _) => extend_value(is_unsigned, mem_read(ReadWrite(Data, Data), addr, 2, aq, aq & rl, true)), + (WORD, _) => extend_value(is_unsigned, mem_read(ReadWrite(Data, Data), addr, 4, aq, aq & rl, true)), + (DOUBLE, 64) => extend_value(is_unsigned, mem_read(ReadWrite(Data, Data), addr, 8, aq, aq & rl, true)), + _ => internal_error(__FILE__, __LINE__, "Unexpected AMO width") + }; + match (mval) { + MemException(e) => { handle_mem_exception(vaddr, e); RETIRE_FAIL }, + MemValue(loaded) => { + let result : xlenbits = + match op { + AMOSWAP => rs2_val, + AMOADD => rs2_val + loaded, + AMOXOR => rs2_val ^ loaded, + AMOAND => rs2_val & loaded, + AMOOR => rs2_val | loaded, + + /* These operations convert bitvectors to integer values using [un]signed, + * and back using to_bits(). + */ + AMOMIN => to_bits(sizeof(xlen), min(signed(rs2_val), signed(loaded))), + AMOMAX => to_bits(sizeof(xlen), max(signed(rs2_val), signed(loaded))), + AMOMINU => to_bits(sizeof(xlen), min(unsigned(rs2_val), unsigned(loaded))), + AMOMAXU => to_bits(sizeof(xlen), max(unsigned(rs2_val), unsigned(loaded))) + }; + let rval : xlenbits = match width { + BYTE => sign_extend(loaded[7..0]), + HALF => sign_extend(loaded[15..0]), + WORD => sign_extend(loaded[31..0]), + DOUBLE => loaded + }; + let wval : MemoryOpResult(bool) = match (width, sizeof(xlen)) { + (BYTE, _) => mem_write_value(addr, 1, result[7..0], aq & rl, rl, true), + (HALF, _) => mem_write_value(addr, 2, result[15..0], aq & rl, rl, true), + (WORD, _) => mem_write_value(addr, 4, result[31..0], aq & rl, rl, true), + (DOUBLE, 64) => mem_write_value(addr, 8, result, aq & rl, rl, true), + _ => internal_error(__FILE__, __LINE__, "Unexpected AMO width") + }; + match (wval) { + MemValue(true) => { X(rd) = rval; RETIRE_SUCCESS }, + MemValue(false) => { internal_error(__FILE__, __LINE__, "AMO got false from mem_write_value") }, + MemException(e) => { handle_mem_exception(vaddr, e); RETIRE_FAIL } + } + } + } + } + } + } + } + } + } + } else { + handle_illegal(); + RETIRE_FAIL + } + } + +# SPDX-SnippetEnd diff --git a/spec/std/isa/inst/Zaamo/amoxor.d.rl.yaml b/spec/std/isa/inst/Zaamo/amoxor.d.rl.yaml new file mode 100644 index 0000000000..ba269fd27e --- /dev/null +++ b/spec/std/isa/inst/Zaamo/amoxor.d.rl.yaml @@ -0,0 +1,140 @@ +# Copyright (c) Qualcomm Technologies, Inc. and/or its subsidiaries. + +# WARNING: This file is auto-generated from spec/std/isa/inst/Zaamo/amoxor.SIZE.AQRL.layout# Copyright (c) Abhijit Das(Sukuna0007Abhi) +# SPDX-License-Identifier: BSD-3-Clause-Clear + +# yaml-language-server: $schema=../../../../schemas/inst_schema.json + +$schema: "inst_schema.json#" +kind: instruction +name: amoxor.d.rl +long_name: Atomic fetch-and-xor doubleword (release) +description: | + Atomically with release ordering: + + * Load the doubleword at address _xs1_ + * Write the loaded value into _xd_ + * XOR the value of register _xs2_ to the loaded value + * Write the result to the address in _xs1_ +definedBy: Zaamo +base: 64 +assembly: xd, xs2, (xs1) +encoding: + match: 0010001----------011-----0101111 + variables: + - name: xs2 + location: 24-20 + - name: xs1 + location: 19-15 + - name: xd + location: 11-7 +access: + s: always + u: always + vs: always + vu: always +operation(): | + if (!implemented?(ExtensionName::A) || (MISA_CSR_IMPLEMENTED && (CSR[misa].A == 1'b0))) { + raise (ExceptionCode::IllegalInstruction, mode(), $encoding); + } + + XReg virtual_address = X[xs1]; + X[xd] = amo<64>(virtual_address, X[xs2], AmoOperation::Xor, 1'b0, 1'b1, $encoding); + + memory_model_release(); + +# SPDX-SnippetBegin +# SPDX-FileCopyrightText: 2017-2025 Contributors to the RISCV Sail Model +# SPDX-License-Identifier: BSD-2-Clause +sail(): | + { + if extension("A") then { + /* Get the address, X(rs1) (no offset). + * Some extensions perform additional checks on address validity. + */ + match ext_data_get_addr(rs1, zeros(), ReadWrite(Data, Data), width) { + Ext_DataAddr_Error(e) => { ext_handle_data_check_error(e); RETIRE_FAIL }, + Ext_DataAddr_OK(vaddr) => { + match translateAddr(vaddr, ReadWrite(Data, Data)) { + TR_Failure(e, _) => { handle_mem_exception(vaddr, e); RETIRE_FAIL }, + TR_Address(addr, _) => { + let eares : MemoryOpResult(unit) = match (width, sizeof(xlen)) { + (BYTE, _) => mem_write_ea(addr, 1, aq & rl, rl, true), + (HALF, _) => mem_write_ea(addr, 2, aq & rl, rl, true), + (WORD, _) => mem_write_ea(addr, 4, aq & rl, rl, true), + (DOUBLE, 64) => mem_write_ea(addr, 8, aq & rl, rl, true), + _ => internal_error(__FILE__, __LINE__, "Unexpected AMO width") + }; + let is_unsigned : bool = match op { + AMOMINU => true, + AMOMAXU => true, + _ => false + }; + let rs2_val : xlenbits = match width { + BYTE => if is_unsigned then zero_extend(X(rs2)[7..0]) else sign_extend(X(rs2)[7..0]), + HALF => if is_unsigned then zero_extend(X(rs2)[15..0]) else sign_extend(X(rs2)[15..0]), + WORD => if is_unsigned then zero_extend(X(rs2)[31..0]) else sign_extend(X(rs2)[31..0]), + DOUBLE => X(rs2) + }; + match (eares) { + MemException(e) => { handle_mem_exception(vaddr, e); RETIRE_FAIL }, + MemValue(_) => { + let mval : MemoryOpResult(xlenbits) = match (width, sizeof(xlen)) { + (BYTE, _) => extend_value(is_unsigned, mem_read(ReadWrite(Data, Data), addr, 1, aq, aq & rl, true)), + (HALF, _) => extend_value(is_unsigned, mem_read(ReadWrite(Data, Data), addr, 2, aq, aq & rl, true)), + (WORD, _) => extend_value(is_unsigned, mem_read(ReadWrite(Data, Data), addr, 4, aq, aq & rl, true)), + (DOUBLE, 64) => extend_value(is_unsigned, mem_read(ReadWrite(Data, Data), addr, 8, aq, aq & rl, true)), + _ => internal_error(__FILE__, __LINE__, "Unexpected AMO width") + }; + match (mval) { + MemException(e) => { handle_mem_exception(vaddr, e); RETIRE_FAIL }, + MemValue(loaded) => { + let result : xlenbits = + match op { + AMOSWAP => rs2_val, + AMOADD => rs2_val + loaded, + AMOXOR => rs2_val ^ loaded, + AMOAND => rs2_val & loaded, + AMOOR => rs2_val | loaded, + + /* These operations convert bitvectors to integer values using [un]signed, + * and back using to_bits(). + */ + AMOMIN => to_bits(sizeof(xlen), min(signed(rs2_val), signed(loaded))), + AMOMAX => to_bits(sizeof(xlen), max(signed(rs2_val), signed(loaded))), + AMOMINU => to_bits(sizeof(xlen), min(unsigned(rs2_val), unsigned(loaded))), + AMOMAXU => to_bits(sizeof(xlen), max(unsigned(rs2_val), unsigned(loaded))) + }; + let rval : xlenbits = match width { + BYTE => sign_extend(loaded[7..0]), + HALF => sign_extend(loaded[15..0]), + WORD => sign_extend(loaded[31..0]), + DOUBLE => loaded + }; + let wval : MemoryOpResult(bool) = match (width, sizeof(xlen)) { + (BYTE, _) => mem_write_value(addr, 1, result[7..0], aq & rl, rl, true), + (HALF, _) => mem_write_value(addr, 2, result[15..0], aq & rl, rl, true), + (WORD, _) => mem_write_value(addr, 4, result[31..0], aq & rl, rl, true), + (DOUBLE, 64) => mem_write_value(addr, 8, result, aq & rl, rl, true), + _ => internal_error(__FILE__, __LINE__, "Unexpected AMO width") + }; + match (wval) { + MemValue(true) => { X(rd) = rval; RETIRE_SUCCESS }, + MemValue(false) => { internal_error(__FILE__, __LINE__, "AMO got false from mem_write_value") }, + MemException(e) => { handle_mem_exception(vaddr, e); RETIRE_FAIL } + } + } + } + } + } + } + } + } + } + } else { + handle_illegal(); + RETIRE_FAIL + } + } + +# SPDX-SnippetEnd diff --git a/spec/std/isa/inst/Zaamo/amoxor.d.yaml b/spec/std/isa/inst/Zaamo/amoxor.d.yaml index ee24a78bf0..b264591be5 100644 --- a/spec/std/isa/inst/Zaamo/amoxor.d.yaml +++ b/spec/std/isa/inst/Zaamo/amoxor.d.yaml @@ -1,4 +1,6 @@ # Copyright (c) Qualcomm Technologies, Inc. and/or its subsidiaries. + +# WARNING: This file is auto-generated from spec/std/isa/inst/Zaamo/amoxor.SIZE.AQRL.layout# Copyright (c) Abhijit Das(Sukuna0007Abhi) # SPDX-License-Identifier: BSD-3-Clause-Clear # yaml-language-server: $schema=../../../../schemas/inst_schema.json @@ -18,12 +20,8 @@ definedBy: Zaamo base: 64 assembly: xd, xs2, (xs1) encoding: - match: 00100------------011-----0101111 + match: 0010000----------011-----0101111 variables: - - name: aq - location: 26 - - name: rl - location: 25 - name: xs2 location: 24-20 - name: xs1 @@ -36,15 +34,12 @@ access: vs: always vu: always operation(): | - if (implemented?(ExtensionName::A) && (CSR[misa].A == 1'b0)) { - # even though this is a memory operation, the exception occurs before that would be known, - # so mode() is the correct reporting mode rathat than effective_ldst_mode() + if (!implemented?(ExtensionName::A) || (MISA_CSR_IMPLEMENTED && (CSR[misa].A == 1'b0))) { raise (ExceptionCode::IllegalInstruction, mode(), $encoding); } XReg virtual_address = X[xs1]; - - X[xd] = amo<64>(virtual_address, X[xs2], AmoOperation::Xor, aq, rl, $encoding); + X[xd] = amo<64>(virtual_address, X[xs2], AmoOperation::Xor, 1'b0, 1'b0, $encoding); # SPDX-SnippetBegin # SPDX-FileCopyrightText: 2017-2025 Contributors to the RISCV Sail Model diff --git a/spec/std/isa/inst/Zaamo/amoxor.w.aq.yaml b/spec/std/isa/inst/Zaamo/amoxor.w.aq.yaml new file mode 100644 index 0000000000..1100dc5a47 --- /dev/null +++ b/spec/std/isa/inst/Zaamo/amoxor.w.aq.yaml @@ -0,0 +1,139 @@ +# Copyright (c) Qualcomm Technologies, Inc. and/or its subsidiaries. + +# WARNING: This file is auto-generated from spec/std/isa/inst/Zaamo/amoxor.SIZE.AQRL.layout# Copyright (c) Abhijit Das(Sukuna0007Abhi) +# SPDX-License-Identifier: BSD-3-Clause-Clear + +# yaml-language-server: $schema=../../../../schemas/inst_schema.json + +$schema: "inst_schema.json#" +kind: instruction +name: amoxor.w.aq +long_name: Atomic fetch-and-xor word (acquire) +description: | + Atomically with acquire ordering: + + * Load the word at address _xs1_ + * Write the sign-extended value into _xd_ + * XOR the least-significant word of register _xs2_ to the loaded value + * Write the result to the address in _xs1_ +definedBy: Zaamo +assembly: xd, xs2, (xs1) +encoding: + match: 0010010----------010-----0101111 + variables: + - name: xs2 + location: 24-20 + - name: xs1 + location: 19-15 + - name: xd + location: 11-7 +access: + s: always + u: always + vs: always + vu: always +operation(): | + if (!implemented?(ExtensionName::A) || (MISA_CSR_IMPLEMENTED && (CSR[misa].A == 1'b0))) { + raise (ExceptionCode::IllegalInstruction, mode(), $encoding); + } + + memory_model_acquire(); + + XReg virtual_address = X[xs1]; + X[xd] = amo<32>(virtual_address, X[xs2][31:0], AmoOperation::Xor, 1'b1, 1'b0, $encoding); + +# SPDX-SnippetBegin +# SPDX-FileCopyrightText: 2017-2025 Contributors to the RISCV Sail Model +# SPDX-License-Identifier: BSD-2-Clause +sail(): | + { + if extension("A") then { + /* Get the address, X(rs1) (no offset). + * Some extensions perform additional checks on address validity. + */ + match ext_data_get_addr(rs1, zeros(), ReadWrite(Data, Data), width) { + Ext_DataAddr_Error(e) => { ext_handle_data_check_error(e); RETIRE_FAIL }, + Ext_DataAddr_OK(vaddr) => { + match translateAddr(vaddr, ReadWrite(Data, Data)) { + TR_Failure(e, _) => { handle_mem_exception(vaddr, e); RETIRE_FAIL }, + TR_Address(addr, _) => { + let eares : MemoryOpResult(unit) = match (width, sizeof(xlen)) { + (BYTE, _) => mem_write_ea(addr, 1, aq & rl, rl, true), + (HALF, _) => mem_write_ea(addr, 2, aq & rl, rl, true), + (WORD, _) => mem_write_ea(addr, 4, aq & rl, rl, true), + (DOUBLE, 64) => mem_write_ea(addr, 8, aq & rl, rl, true), + _ => internal_error(__FILE__, __LINE__, "Unexpected AMO width") + }; + let is_unsigned : bool = match op { + AMOMINU => true, + AMOMAXU => true, + _ => false + }; + let rs2_val : xlenbits = match width { + BYTE => if is_unsigned then zero_extend(X(rs2)[7..0]) else sign_extend(X(rs2)[7..0]), + HALF => if is_unsigned then zero_extend(X(rs2)[15..0]) else sign_extend(X(rs2)[15..0]), + WORD => if is_unsigned then zero_extend(X(rs2)[31..0]) else sign_extend(X(rs2)[31..0]), + DOUBLE => X(rs2) + }; + match (eares) { + MemException(e) => { handle_mem_exception(vaddr, e); RETIRE_FAIL }, + MemValue(_) => { + let mval : MemoryOpResult(xlenbits) = match (width, sizeof(xlen)) { + (BYTE, _) => extend_value(is_unsigned, mem_read(ReadWrite(Data, Data), addr, 1, aq, aq & rl, true)), + (HALF, _) => extend_value(is_unsigned, mem_read(ReadWrite(Data, Data), addr, 2, aq, aq & rl, true)), + (WORD, _) => extend_value(is_unsigned, mem_read(ReadWrite(Data, Data), addr, 4, aq, aq & rl, true)), + (DOUBLE, 64) => extend_value(is_unsigned, mem_read(ReadWrite(Data, Data), addr, 8, aq, aq & rl, true)), + _ => internal_error(__FILE__, __LINE__, "Unexpected AMO width") + }; + match (mval) { + MemException(e) => { handle_mem_exception(vaddr, e); RETIRE_FAIL }, + MemValue(loaded) => { + let result : xlenbits = + match op { + AMOSWAP => rs2_val, + AMOADD => rs2_val + loaded, + AMOXOR => rs2_val ^ loaded, + AMOAND => rs2_val & loaded, + AMOOR => rs2_val | loaded, + + /* These operations convert bitvectors to integer values using [un]signed, + * and back using to_bits(). + */ + AMOMIN => to_bits(sizeof(xlen), min(signed(rs2_val), signed(loaded))), + AMOMAX => to_bits(sizeof(xlen), max(signed(rs2_val), signed(loaded))), + AMOMINU => to_bits(sizeof(xlen), min(unsigned(rs2_val), unsigned(loaded))), + AMOMAXU => to_bits(sizeof(xlen), max(unsigned(rs2_val), unsigned(loaded))) + }; + let rval : xlenbits = match width { + BYTE => sign_extend(loaded[7..0]), + HALF => sign_extend(loaded[15..0]), + WORD => sign_extend(loaded[31..0]), + DOUBLE => loaded + }; + let wval : MemoryOpResult(bool) = match (width, sizeof(xlen)) { + (BYTE, _) => mem_write_value(addr, 1, result[7..0], aq & rl, rl, true), + (HALF, _) => mem_write_value(addr, 2, result[15..0], aq & rl, rl, true), + (WORD, _) => mem_write_value(addr, 4, result[31..0], aq & rl, rl, true), + (DOUBLE, 64) => mem_write_value(addr, 8, result, aq & rl, rl, true), + _ => internal_error(__FILE__, __LINE__, "Unexpected AMO width") + }; + match (wval) { + MemValue(true) => { X(rd) = rval; RETIRE_SUCCESS }, + MemValue(false) => { internal_error(__FILE__, __LINE__, "AMO got false from mem_write_value") }, + MemException(e) => { handle_mem_exception(vaddr, e); RETIRE_FAIL } + } + } + } + } + } + } + } + } + } + } else { + handle_illegal(); + RETIRE_FAIL + } + } + +# SPDX-SnippetEnd diff --git a/spec/std/isa/inst/Zaamo/amoxor.w.aqrl.yaml b/spec/std/isa/inst/Zaamo/amoxor.w.aqrl.yaml new file mode 100644 index 0000000000..3f2530bcf8 --- /dev/null +++ b/spec/std/isa/inst/Zaamo/amoxor.w.aqrl.yaml @@ -0,0 +1,141 @@ +# Copyright (c) Qualcomm Technologies, Inc. and/or its subsidiaries. + +# WARNING: This file is auto-generated from spec/std/isa/inst/Zaamo/amoxor.SIZE.AQRL.layout# Copyright (c) Abhijit Das(Sukuna0007Abhi) +# SPDX-License-Identifier: BSD-3-Clause-Clear + +# yaml-language-server: $schema=../../../../schemas/inst_schema.json + +$schema: "inst_schema.json#" +kind: instruction +name: amoxor.w.aqrl +long_name: Atomic fetch-and-xor word (acquire-release) +description: | + Atomically with acquire and release ordering: + + * Load the word at address _xs1_ + * Write the sign-extended value into _xd_ + * XOR the least-significant word of register _xs2_ to the loaded value + * Write the result to the address in _xs1_ +definedBy: Zaamo +assembly: xd, xs2, (xs1) +encoding: + match: 0010011----------010-----0101111 + variables: + - name: xs2 + location: 24-20 + - name: xs1 + location: 19-15 + - name: xd + location: 11-7 +access: + s: always + u: always + vs: always + vu: always +operation(): | + if (!implemented?(ExtensionName::A) || (MISA_CSR_IMPLEMENTED && (CSR[misa].A == 1'b0))) { + raise (ExceptionCode::IllegalInstruction, mode(), $encoding); + } + + memory_model_acquire(); + + XReg virtual_address = X[xs1]; + X[xd] = amo<32>(virtual_address, X[xs2][31:0], AmoOperation::Xor, 1'b1, 1'b1, $encoding); + + memory_model_release(); + +# SPDX-SnippetBegin +# SPDX-FileCopyrightText: 2017-2025 Contributors to the RISCV Sail Model +# SPDX-License-Identifier: BSD-2-Clause +sail(): | + { + if extension("A") then { + /* Get the address, X(rs1) (no offset). + * Some extensions perform additional checks on address validity. + */ + match ext_data_get_addr(rs1, zeros(), ReadWrite(Data, Data), width) { + Ext_DataAddr_Error(e) => { ext_handle_data_check_error(e); RETIRE_FAIL }, + Ext_DataAddr_OK(vaddr) => { + match translateAddr(vaddr, ReadWrite(Data, Data)) { + TR_Failure(e, _) => { handle_mem_exception(vaddr, e); RETIRE_FAIL }, + TR_Address(addr, _) => { + let eares : MemoryOpResult(unit) = match (width, sizeof(xlen)) { + (BYTE, _) => mem_write_ea(addr, 1, aq & rl, rl, true), + (HALF, _) => mem_write_ea(addr, 2, aq & rl, rl, true), + (WORD, _) => mem_write_ea(addr, 4, aq & rl, rl, true), + (DOUBLE, 64) => mem_write_ea(addr, 8, aq & rl, rl, true), + _ => internal_error(__FILE__, __LINE__, "Unexpected AMO width") + }; + let is_unsigned : bool = match op { + AMOMINU => true, + AMOMAXU => true, + _ => false + }; + let rs2_val : xlenbits = match width { + BYTE => if is_unsigned then zero_extend(X(rs2)[7..0]) else sign_extend(X(rs2)[7..0]), + HALF => if is_unsigned then zero_extend(X(rs2)[15..0]) else sign_extend(X(rs2)[15..0]), + WORD => if is_unsigned then zero_extend(X(rs2)[31..0]) else sign_extend(X(rs2)[31..0]), + DOUBLE => X(rs2) + }; + match (eares) { + MemException(e) => { handle_mem_exception(vaddr, e); RETIRE_FAIL }, + MemValue(_) => { + let mval : MemoryOpResult(xlenbits) = match (width, sizeof(xlen)) { + (BYTE, _) => extend_value(is_unsigned, mem_read(ReadWrite(Data, Data), addr, 1, aq, aq & rl, true)), + (HALF, _) => extend_value(is_unsigned, mem_read(ReadWrite(Data, Data), addr, 2, aq, aq & rl, true)), + (WORD, _) => extend_value(is_unsigned, mem_read(ReadWrite(Data, Data), addr, 4, aq, aq & rl, true)), + (DOUBLE, 64) => extend_value(is_unsigned, mem_read(ReadWrite(Data, Data), addr, 8, aq, aq & rl, true)), + _ => internal_error(__FILE__, __LINE__, "Unexpected AMO width") + }; + match (mval) { + MemException(e) => { handle_mem_exception(vaddr, e); RETIRE_FAIL }, + MemValue(loaded) => { + let result : xlenbits = + match op { + AMOSWAP => rs2_val, + AMOADD => rs2_val + loaded, + AMOXOR => rs2_val ^ loaded, + AMOAND => rs2_val & loaded, + AMOOR => rs2_val | loaded, + + /* These operations convert bitvectors to integer values using [un]signed, + * and back using to_bits(). + */ + AMOMIN => to_bits(sizeof(xlen), min(signed(rs2_val), signed(loaded))), + AMOMAX => to_bits(sizeof(xlen), max(signed(rs2_val), signed(loaded))), + AMOMINU => to_bits(sizeof(xlen), min(unsigned(rs2_val), unsigned(loaded))), + AMOMAXU => to_bits(sizeof(xlen), max(unsigned(rs2_val), unsigned(loaded))) + }; + let rval : xlenbits = match width { + BYTE => sign_extend(loaded[7..0]), + HALF => sign_extend(loaded[15..0]), + WORD => sign_extend(loaded[31..0]), + DOUBLE => loaded + }; + let wval : MemoryOpResult(bool) = match (width, sizeof(xlen)) { + (BYTE, _) => mem_write_value(addr, 1, result[7..0], aq & rl, rl, true), + (HALF, _) => mem_write_value(addr, 2, result[15..0], aq & rl, rl, true), + (WORD, _) => mem_write_value(addr, 4, result[31..0], aq & rl, rl, true), + (DOUBLE, 64) => mem_write_value(addr, 8, result, aq & rl, rl, true), + _ => internal_error(__FILE__, __LINE__, "Unexpected AMO width") + }; + match (wval) { + MemValue(true) => { X(rd) = rval; RETIRE_SUCCESS }, + MemValue(false) => { internal_error(__FILE__, __LINE__, "AMO got false from mem_write_value") }, + MemException(e) => { handle_mem_exception(vaddr, e); RETIRE_FAIL } + } + } + } + } + } + } + } + } + } + } else { + handle_illegal(); + RETIRE_FAIL + } + } + +# SPDX-SnippetEnd diff --git a/spec/std/isa/inst/Zaamo/amoxor.w.rl.yaml b/spec/std/isa/inst/Zaamo/amoxor.w.rl.yaml new file mode 100644 index 0000000000..3afd23841c --- /dev/null +++ b/spec/std/isa/inst/Zaamo/amoxor.w.rl.yaml @@ -0,0 +1,139 @@ +# Copyright (c) Qualcomm Technologies, Inc. and/or its subsidiaries. + +# WARNING: This file is auto-generated from spec/std/isa/inst/Zaamo/amoxor.SIZE.AQRL.layout# Copyright (c) Abhijit Das(Sukuna0007Abhi) +# SPDX-License-Identifier: BSD-3-Clause-Clear + +# yaml-language-server: $schema=../../../../schemas/inst_schema.json + +$schema: "inst_schema.json#" +kind: instruction +name: amoxor.w.rl +long_name: Atomic fetch-and-xor word (release) +description: | + Atomically with release ordering: + + * Load the word at address _xs1_ + * Write the sign-extended value into _xd_ + * XOR the least-significant word of register _xs2_ to the loaded value + * Write the result to the address in _xs1_ +definedBy: Zaamo +assembly: xd, xs2, (xs1) +encoding: + match: 0010001----------010-----0101111 + variables: + - name: xs2 + location: 24-20 + - name: xs1 + location: 19-15 + - name: xd + location: 11-7 +access: + s: always + u: always + vs: always + vu: always +operation(): | + if (!implemented?(ExtensionName::A) || (MISA_CSR_IMPLEMENTED && (CSR[misa].A == 1'b0))) { + raise (ExceptionCode::IllegalInstruction, mode(), $encoding); + } + + XReg virtual_address = X[xs1]; + X[xd] = amo<32>(virtual_address, X[xs2][31:0], AmoOperation::Xor, 1'b0, 1'b1, $encoding); + + memory_model_release(); + +# SPDX-SnippetBegin +# SPDX-FileCopyrightText: 2017-2025 Contributors to the RISCV Sail Model +# SPDX-License-Identifier: BSD-2-Clause +sail(): | + { + if extension("A") then { + /* Get the address, X(rs1) (no offset). + * Some extensions perform additional checks on address validity. + */ + match ext_data_get_addr(rs1, zeros(), ReadWrite(Data, Data), width) { + Ext_DataAddr_Error(e) => { ext_handle_data_check_error(e); RETIRE_FAIL }, + Ext_DataAddr_OK(vaddr) => { + match translateAddr(vaddr, ReadWrite(Data, Data)) { + TR_Failure(e, _) => { handle_mem_exception(vaddr, e); RETIRE_FAIL }, + TR_Address(addr, _) => { + let eares : MemoryOpResult(unit) = match (width, sizeof(xlen)) { + (BYTE, _) => mem_write_ea(addr, 1, aq & rl, rl, true), + (HALF, _) => mem_write_ea(addr, 2, aq & rl, rl, true), + (WORD, _) => mem_write_ea(addr, 4, aq & rl, rl, true), + (DOUBLE, 64) => mem_write_ea(addr, 8, aq & rl, rl, true), + _ => internal_error(__FILE__, __LINE__, "Unexpected AMO width") + }; + let is_unsigned : bool = match op { + AMOMINU => true, + AMOMAXU => true, + _ => false + }; + let rs2_val : xlenbits = match width { + BYTE => if is_unsigned then zero_extend(X(rs2)[7..0]) else sign_extend(X(rs2)[7..0]), + HALF => if is_unsigned then zero_extend(X(rs2)[15..0]) else sign_extend(X(rs2)[15..0]), + WORD => if is_unsigned then zero_extend(X(rs2)[31..0]) else sign_extend(X(rs2)[31..0]), + DOUBLE => X(rs2) + }; + match (eares) { + MemException(e) => { handle_mem_exception(vaddr, e); RETIRE_FAIL }, + MemValue(_) => { + let mval : MemoryOpResult(xlenbits) = match (width, sizeof(xlen)) { + (BYTE, _) => extend_value(is_unsigned, mem_read(ReadWrite(Data, Data), addr, 1, aq, aq & rl, true)), + (HALF, _) => extend_value(is_unsigned, mem_read(ReadWrite(Data, Data), addr, 2, aq, aq & rl, true)), + (WORD, _) => extend_value(is_unsigned, mem_read(ReadWrite(Data, Data), addr, 4, aq, aq & rl, true)), + (DOUBLE, 64) => extend_value(is_unsigned, mem_read(ReadWrite(Data, Data), addr, 8, aq, aq & rl, true)), + _ => internal_error(__FILE__, __LINE__, "Unexpected AMO width") + }; + match (mval) { + MemException(e) => { handle_mem_exception(vaddr, e); RETIRE_FAIL }, + MemValue(loaded) => { + let result : xlenbits = + match op { + AMOSWAP => rs2_val, + AMOADD => rs2_val + loaded, + AMOXOR => rs2_val ^ loaded, + AMOAND => rs2_val & loaded, + AMOOR => rs2_val | loaded, + + /* These operations convert bitvectors to integer values using [un]signed, + * and back using to_bits(). + */ + AMOMIN => to_bits(sizeof(xlen), min(signed(rs2_val), signed(loaded))), + AMOMAX => to_bits(sizeof(xlen), max(signed(rs2_val), signed(loaded))), + AMOMINU => to_bits(sizeof(xlen), min(unsigned(rs2_val), unsigned(loaded))), + AMOMAXU => to_bits(sizeof(xlen), max(unsigned(rs2_val), unsigned(loaded))) + }; + let rval : xlenbits = match width { + BYTE => sign_extend(loaded[7..0]), + HALF => sign_extend(loaded[15..0]), + WORD => sign_extend(loaded[31..0]), + DOUBLE => loaded + }; + let wval : MemoryOpResult(bool) = match (width, sizeof(xlen)) { + (BYTE, _) => mem_write_value(addr, 1, result[7..0], aq & rl, rl, true), + (HALF, _) => mem_write_value(addr, 2, result[15..0], aq & rl, rl, true), + (WORD, _) => mem_write_value(addr, 4, result[31..0], aq & rl, rl, true), + (DOUBLE, 64) => mem_write_value(addr, 8, result, aq & rl, rl, true), + _ => internal_error(__FILE__, __LINE__, "Unexpected AMO width") + }; + match (wval) { + MemValue(true) => { X(rd) = rval; RETIRE_SUCCESS }, + MemValue(false) => { internal_error(__FILE__, __LINE__, "AMO got false from mem_write_value") }, + MemException(e) => { handle_mem_exception(vaddr, e); RETIRE_FAIL } + } + } + } + } + } + } + } + } + } + } else { + handle_illegal(); + RETIRE_FAIL + } + } + +# SPDX-SnippetEnd diff --git a/spec/std/isa/inst/Zaamo/amoxor.w.yaml b/spec/std/isa/inst/Zaamo/amoxor.w.yaml index 5e218ef1e2..c891661465 100644 --- a/spec/std/isa/inst/Zaamo/amoxor.w.yaml +++ b/spec/std/isa/inst/Zaamo/amoxor.w.yaml @@ -1,4 +1,6 @@ # Copyright (c) Qualcomm Technologies, Inc. and/or its subsidiaries. + +# WARNING: This file is auto-generated from spec/std/isa/inst/Zaamo/amoxor.SIZE.AQRL.layout# Copyright (c) Abhijit Das(Sukuna0007Abhi) # SPDX-License-Identifier: BSD-3-Clause-Clear # yaml-language-server: $schema=../../../../schemas/inst_schema.json @@ -17,12 +19,8 @@ description: | definedBy: Zaamo assembly: xd, xs2, (xs1) encoding: - match: 00100------------010-----0101111 + match: 0010000----------010-----0101111 variables: - - name: aq - location: 26 - - name: rl - location: 25 - name: xs2 location: 24-20 - name: xs1 @@ -35,15 +33,12 @@ access: vs: always vu: always operation(): | - if (implemented?(ExtensionName::A) && (CSR[misa].A == 1'b0)) { - # even though this is a memory operation, the exception occurs before that would be known, - # so mode() is the correct reporting mode rathat than effective_ldst_mode() + if (!implemented?(ExtensionName::A) || (MISA_CSR_IMPLEMENTED && (CSR[misa].A == 1'b0))) { raise (ExceptionCode::IllegalInstruction, mode(), $encoding); } XReg virtual_address = X[xs1]; - - X[xd] = amo<32>(virtual_address, X[xs2][31:0], AmoOperation::Xor, aq, rl, $encoding); + X[xd] = amo<32>(virtual_address, X[xs2][31:0], AmoOperation::Xor, 1'b0, 1'b0, $encoding); # SPDX-SnippetBegin # SPDX-FileCopyrightText: 2017-2025 Contributors to the RISCV Sail Model diff --git a/spec/std/isa/inst/Zabha/amoadd.b.aq.yaml b/spec/std/isa/inst/Zabha/amoadd.b.aq.yaml new file mode 100644 index 0000000000..33c5aea416 --- /dev/null +++ b/spec/std/isa/inst/Zabha/amoadd.b.aq.yaml @@ -0,0 +1,139 @@ +# Copyright (c) Qualcomm Technologies, Inc. and/or its subsidiaries. + +# WARNING: This file is auto-generated from spec/std/isa/inst/Zaamo/amoadd.SIZE.AQRL.layout# Copyright (c) Abhijit Das(Sukuna0007Abhi) +# SPDX-License-Identifier: BSD-3-Clause-Clear + +# yaml-language-server: $schema=../../../../schemas/inst_schema.json + +$schema: "inst_schema.json#" +kind: instruction +name: amoadd.b.aq +long_name: Atomic fetch-and-add byte (acquire) +description: | + Atomically with acquire ordering: + + * Load the byte at address _xs1_ + * Write the sign-extended value into _xd_ + * Add the least-significant byte of register _xs2_ to the loaded value + * Write the result to the address in _xs1_ +definedBy: Zabha +assembly: xd, xs2, (xs1) +encoding: + match: 0000010----------000-----0101111 + variables: + - name: xs2 + location: 24-20 + - name: xs1 + location: 19-15 + - name: xd + location: 11-7 +access: + s: always + u: always + vs: always + vu: always +operation(): | + if (!implemented?(ExtensionName::A) || (MISA_CSR_IMPLEMENTED && (CSR[misa].A == 1'b0))) { + raise (ExceptionCode::IllegalInstruction, mode(), $encoding); + } + + memory_model_acquire(); + + XReg virtual_address = X[xs1]; + X[xd] = amo<8>(virtual_address, X[xs2][7:0], AmoOperation::Add, 1'b1, 1'b0, $encoding); + +# SPDX-SnippetBegin +# SPDX-FileCopyrightText: 2017-2025 Contributors to the RISCV Sail Model +# SPDX-License-Identifier: BSD-2-Clause +sail(): | + { + if extension("A") then { + /* Get the address, X(rs1) (no offset). + * Some extensions perform additional checks on address validity. + */ + match ext_data_get_addr(rs1, zeros(), ReadWrite(Data, Data), width) { + Ext_DataAddr_Error(e) => { ext_handle_data_check_error(e); RETIRE_FAIL }, + Ext_DataAddr_OK(vaddr) => { + match translateAddr(vaddr, ReadWrite(Data, Data)) { + TR_Failure(e, _) => { handle_mem_exception(vaddr, e); RETIRE_FAIL }, + TR_Address(addr, _) => { + let eares : MemoryOpResult(unit) = match (width, sizeof(xlen)) { + (BYTE, _) => mem_write_ea(addr, 1, aq & rl, rl, true), + (HALF, _) => mem_write_ea(addr, 2, aq & rl, rl, true), + (WORD, _) => mem_write_ea(addr, 4, aq & rl, rl, true), + (DOUBLE, 64) => mem_write_ea(addr, 8, aq & rl, rl, true), + _ => internal_error(__FILE__, __LINE__, "Unexpected AMO width") + }; + let is_unsigned : bool = match op { + AMOMINU => true, + AMOMAXU => true, + _ => false + }; + let rs2_val : xlenbits = match width { + BYTE => if is_unsigned then zero_extend(X(rs2)[7..0]) else sign_extend(X(rs2)[7..0]), + HALF => if is_unsigned then zero_extend(X(rs2)[15..0]) else sign_extend(X(rs2)[15..0]), + WORD => if is_unsigned then zero_extend(X(rs2)[31..0]) else sign_extend(X(rs2)[31..0]), + DOUBLE => X(rs2) + }; + match (eares) { + MemException(e) => { handle_mem_exception(vaddr, e); RETIRE_FAIL }, + MemValue(_) => { + let mval : MemoryOpResult(xlenbits) = match (width, sizeof(xlen)) { + (BYTE, _) => extend_value(is_unsigned, mem_read(ReadWrite(Data, Data), addr, 1, aq, aq & rl, true)), + (HALF, _) => extend_value(is_unsigned, mem_read(ReadWrite(Data, Data), addr, 2, aq, aq & rl, true)), + (WORD, _) => extend_value(is_unsigned, mem_read(ReadWrite(Data, Data), addr, 4, aq, aq & rl, true)), + (DOUBLE, 64) => extend_value(is_unsigned, mem_read(ReadWrite(Data, Data), addr, 8, aq, aq & rl, true)), + _ => internal_error(__FILE__, __LINE__, "Unexpected AMO width") + }; + match (mval) { + MemException(e) => { handle_mem_exception(vaddr, e); RETIRE_FAIL }, + MemValue(loaded) => { + let result : xlenbits = + match op { + AMOSWAP => rs2_val, + AMOADD => rs2_val + loaded, + AMOXOR => rs2_val ^ loaded, + AMOAND => rs2_val & loaded, + AMOOR => rs2_val | loaded, + + /* These operations convert bitvectors to integer values using [un]signed, + * and back using to_bits(). + */ + AMOMIN => to_bits(sizeof(xlen), min(signed(rs2_val), signed(loaded))), + AMOMAX => to_bits(sizeof(xlen), max(signed(rs2_val), signed(loaded))), + AMOMINU => to_bits(sizeof(xlen), min(unsigned(rs2_val), unsigned(loaded))), + AMOMAXU => to_bits(sizeof(xlen), max(unsigned(rs2_val), unsigned(loaded))) + }; + let rval : xlenbits = match width { + BYTE => sign_extend(loaded[7..0]), + HALF => sign_extend(loaded[15..0]), + WORD => sign_extend(loaded[31..0]), + DOUBLE => loaded + }; + let wval : MemoryOpResult(bool) = match (width, sizeof(xlen)) { + (BYTE, _) => mem_write_value(addr, 1, result[7..0], aq & rl, rl, true), + (HALF, _) => mem_write_value(addr, 2, result[15..0], aq & rl, rl, true), + (WORD, _) => mem_write_value(addr, 4, result[31..0], aq & rl, rl, true), + (DOUBLE, 64) => mem_write_value(addr, 8, result, aq & rl, rl, true), + _ => internal_error(__FILE__, __LINE__, "Unexpected AMO width") + }; + match (wval) { + MemValue(true) => { X(rd) = rval; RETIRE_SUCCESS }, + MemValue(false) => { internal_error(__FILE__, __LINE__, "AMO got false from mem_write_value") }, + MemException(e) => { handle_mem_exception(vaddr, e); RETIRE_FAIL } + } + } + } + } + } + } + } + } + } + } else { + handle_illegal(); + RETIRE_FAIL + } + } + +# SPDX-SnippetEnd diff --git a/spec/std/isa/inst/Zabha/amoadd.b.aqrl.yaml b/spec/std/isa/inst/Zabha/amoadd.b.aqrl.yaml new file mode 100644 index 0000000000..211d146d92 --- /dev/null +++ b/spec/std/isa/inst/Zabha/amoadd.b.aqrl.yaml @@ -0,0 +1,141 @@ +# Copyright (c) Qualcomm Technologies, Inc. and/or its subsidiaries. + +# WARNING: This file is auto-generated from spec/std/isa/inst/Zaamo/amoadd.SIZE.AQRL.layout# Copyright (c) Abhijit Das(Sukuna0007Abhi) +# SPDX-License-Identifier: BSD-3-Clause-Clear + +# yaml-language-server: $schema=../../../../schemas/inst_schema.json + +$schema: "inst_schema.json#" +kind: instruction +name: amoadd.b.aqrl +long_name: Atomic fetch-and-add byte (acquire-release) +description: | + Atomically with acquire and release ordering: + + * Load the byte at address _xs1_ + * Write the sign-extended value into _xd_ + * Add the least-significant byte of register _xs2_ to the loaded value + * Write the result to the address in _xs1_ +definedBy: Zabha +assembly: xd, xs2, (xs1) +encoding: + match: 0000011----------000-----0101111 + variables: + - name: xs2 + location: 24-20 + - name: xs1 + location: 19-15 + - name: xd + location: 11-7 +access: + s: always + u: always + vs: always + vu: always +operation(): | + if (!implemented?(ExtensionName::A) || (MISA_CSR_IMPLEMENTED && (CSR[misa].A == 1'b0))) { + raise (ExceptionCode::IllegalInstruction, mode(), $encoding); + } + + memory_model_acquire(); + + XReg virtual_address = X[xs1]; + X[xd] = amo<8>(virtual_address, X[xs2][7:0], AmoOperation::Add, 1'b1, 1'b1, $encoding); + + memory_model_release(); + +# SPDX-SnippetBegin +# SPDX-FileCopyrightText: 2017-2025 Contributors to the RISCV Sail Model +# SPDX-License-Identifier: BSD-2-Clause +sail(): | + { + if extension("A") then { + /* Get the address, X(rs1) (no offset). + * Some extensions perform additional checks on address validity. + */ + match ext_data_get_addr(rs1, zeros(), ReadWrite(Data, Data), width) { + Ext_DataAddr_Error(e) => { ext_handle_data_check_error(e); RETIRE_FAIL }, + Ext_DataAddr_OK(vaddr) => { + match translateAddr(vaddr, ReadWrite(Data, Data)) { + TR_Failure(e, _) => { handle_mem_exception(vaddr, e); RETIRE_FAIL }, + TR_Address(addr, _) => { + let eares : MemoryOpResult(unit) = match (width, sizeof(xlen)) { + (BYTE, _) => mem_write_ea(addr, 1, aq & rl, rl, true), + (HALF, _) => mem_write_ea(addr, 2, aq & rl, rl, true), + (WORD, _) => mem_write_ea(addr, 4, aq & rl, rl, true), + (DOUBLE, 64) => mem_write_ea(addr, 8, aq & rl, rl, true), + _ => internal_error(__FILE__, __LINE__, "Unexpected AMO width") + }; + let is_unsigned : bool = match op { + AMOMINU => true, + AMOMAXU => true, + _ => false + }; + let rs2_val : xlenbits = match width { + BYTE => if is_unsigned then zero_extend(X(rs2)[7..0]) else sign_extend(X(rs2)[7..0]), + HALF => if is_unsigned then zero_extend(X(rs2)[15..0]) else sign_extend(X(rs2)[15..0]), + WORD => if is_unsigned then zero_extend(X(rs2)[31..0]) else sign_extend(X(rs2)[31..0]), + DOUBLE => X(rs2) + }; + match (eares) { + MemException(e) => { handle_mem_exception(vaddr, e); RETIRE_FAIL }, + MemValue(_) => { + let mval : MemoryOpResult(xlenbits) = match (width, sizeof(xlen)) { + (BYTE, _) => extend_value(is_unsigned, mem_read(ReadWrite(Data, Data), addr, 1, aq, aq & rl, true)), + (HALF, _) => extend_value(is_unsigned, mem_read(ReadWrite(Data, Data), addr, 2, aq, aq & rl, true)), + (WORD, _) => extend_value(is_unsigned, mem_read(ReadWrite(Data, Data), addr, 4, aq, aq & rl, true)), + (DOUBLE, 64) => extend_value(is_unsigned, mem_read(ReadWrite(Data, Data), addr, 8, aq, aq & rl, true)), + _ => internal_error(__FILE__, __LINE__, "Unexpected AMO width") + }; + match (mval) { + MemException(e) => { handle_mem_exception(vaddr, e); RETIRE_FAIL }, + MemValue(loaded) => { + let result : xlenbits = + match op { + AMOSWAP => rs2_val, + AMOADD => rs2_val + loaded, + AMOXOR => rs2_val ^ loaded, + AMOAND => rs2_val & loaded, + AMOOR => rs2_val | loaded, + + /* These operations convert bitvectors to integer values using [un]signed, + * and back using to_bits(). + */ + AMOMIN => to_bits(sizeof(xlen), min(signed(rs2_val), signed(loaded))), + AMOMAX => to_bits(sizeof(xlen), max(signed(rs2_val), signed(loaded))), + AMOMINU => to_bits(sizeof(xlen), min(unsigned(rs2_val), unsigned(loaded))), + AMOMAXU => to_bits(sizeof(xlen), max(unsigned(rs2_val), unsigned(loaded))) + }; + let rval : xlenbits = match width { + BYTE => sign_extend(loaded[7..0]), + HALF => sign_extend(loaded[15..0]), + WORD => sign_extend(loaded[31..0]), + DOUBLE => loaded + }; + let wval : MemoryOpResult(bool) = match (width, sizeof(xlen)) { + (BYTE, _) => mem_write_value(addr, 1, result[7..0], aq & rl, rl, true), + (HALF, _) => mem_write_value(addr, 2, result[15..0], aq & rl, rl, true), + (WORD, _) => mem_write_value(addr, 4, result[31..0], aq & rl, rl, true), + (DOUBLE, 64) => mem_write_value(addr, 8, result, aq & rl, rl, true), + _ => internal_error(__FILE__, __LINE__, "Unexpected AMO width") + }; + match (wval) { + MemValue(true) => { X(rd) = rval; RETIRE_SUCCESS }, + MemValue(false) => { internal_error(__FILE__, __LINE__, "AMO got false from mem_write_value") }, + MemException(e) => { handle_mem_exception(vaddr, e); RETIRE_FAIL } + } + } + } + } + } + } + } + } + } + } else { + handle_illegal(); + RETIRE_FAIL + } + } + +# SPDX-SnippetEnd diff --git a/spec/std/isa/inst/Zabha/amoadd.b.rl.yaml b/spec/std/isa/inst/Zabha/amoadd.b.rl.yaml new file mode 100644 index 0000000000..7c3fee14f5 --- /dev/null +++ b/spec/std/isa/inst/Zabha/amoadd.b.rl.yaml @@ -0,0 +1,139 @@ +# Copyright (c) Qualcomm Technologies, Inc. and/or its subsidiaries. + +# WARNING: This file is auto-generated from spec/std/isa/inst/Zaamo/amoadd.SIZE.AQRL.layout# Copyright (c) Abhijit Das(Sukuna0007Abhi) +# SPDX-License-Identifier: BSD-3-Clause-Clear + +# yaml-language-server: $schema=../../../../schemas/inst_schema.json + +$schema: "inst_schema.json#" +kind: instruction +name: amoadd.b.rl +long_name: Atomic fetch-and-add byte (release) +description: | + Atomically with release ordering: + + * Load the byte at address _xs1_ + * Write the sign-extended value into _xd_ + * Add the least-significant byte of register _xs2_ to the loaded value + * Write the result to the address in _xs1_ +definedBy: Zabha +assembly: xd, xs2, (xs1) +encoding: + match: 0000001----------000-----0101111 + variables: + - name: xs2 + location: 24-20 + - name: xs1 + location: 19-15 + - name: xd + location: 11-7 +access: + s: always + u: always + vs: always + vu: always +operation(): | + if (!implemented?(ExtensionName::A) || (MISA_CSR_IMPLEMENTED && (CSR[misa].A == 1'b0))) { + raise (ExceptionCode::IllegalInstruction, mode(), $encoding); + } + + XReg virtual_address = X[xs1]; + X[xd] = amo<8>(virtual_address, X[xs2][7:0], AmoOperation::Add, 1'b0, 1'b1, $encoding); + + memory_model_release(); + +# SPDX-SnippetBegin +# SPDX-FileCopyrightText: 2017-2025 Contributors to the RISCV Sail Model +# SPDX-License-Identifier: BSD-2-Clause +sail(): | + { + if extension("A") then { + /* Get the address, X(rs1) (no offset). + * Some extensions perform additional checks on address validity. + */ + match ext_data_get_addr(rs1, zeros(), ReadWrite(Data, Data), width) { + Ext_DataAddr_Error(e) => { ext_handle_data_check_error(e); RETIRE_FAIL }, + Ext_DataAddr_OK(vaddr) => { + match translateAddr(vaddr, ReadWrite(Data, Data)) { + TR_Failure(e, _) => { handle_mem_exception(vaddr, e); RETIRE_FAIL }, + TR_Address(addr, _) => { + let eares : MemoryOpResult(unit) = match (width, sizeof(xlen)) { + (BYTE, _) => mem_write_ea(addr, 1, aq & rl, rl, true), + (HALF, _) => mem_write_ea(addr, 2, aq & rl, rl, true), + (WORD, _) => mem_write_ea(addr, 4, aq & rl, rl, true), + (DOUBLE, 64) => mem_write_ea(addr, 8, aq & rl, rl, true), + _ => internal_error(__FILE__, __LINE__, "Unexpected AMO width") + }; + let is_unsigned : bool = match op { + AMOMINU => true, + AMOMAXU => true, + _ => false + }; + let rs2_val : xlenbits = match width { + BYTE => if is_unsigned then zero_extend(X(rs2)[7..0]) else sign_extend(X(rs2)[7..0]), + HALF => if is_unsigned then zero_extend(X(rs2)[15..0]) else sign_extend(X(rs2)[15..0]), + WORD => if is_unsigned then zero_extend(X(rs2)[31..0]) else sign_extend(X(rs2)[31..0]), + DOUBLE => X(rs2) + }; + match (eares) { + MemException(e) => { handle_mem_exception(vaddr, e); RETIRE_FAIL }, + MemValue(_) => { + let mval : MemoryOpResult(xlenbits) = match (width, sizeof(xlen)) { + (BYTE, _) => extend_value(is_unsigned, mem_read(ReadWrite(Data, Data), addr, 1, aq, aq & rl, true)), + (HALF, _) => extend_value(is_unsigned, mem_read(ReadWrite(Data, Data), addr, 2, aq, aq & rl, true)), + (WORD, _) => extend_value(is_unsigned, mem_read(ReadWrite(Data, Data), addr, 4, aq, aq & rl, true)), + (DOUBLE, 64) => extend_value(is_unsigned, mem_read(ReadWrite(Data, Data), addr, 8, aq, aq & rl, true)), + _ => internal_error(__FILE__, __LINE__, "Unexpected AMO width") + }; + match (mval) { + MemException(e) => { handle_mem_exception(vaddr, e); RETIRE_FAIL }, + MemValue(loaded) => { + let result : xlenbits = + match op { + AMOSWAP => rs2_val, + AMOADD => rs2_val + loaded, + AMOXOR => rs2_val ^ loaded, + AMOAND => rs2_val & loaded, + AMOOR => rs2_val | loaded, + + /* These operations convert bitvectors to integer values using [un]signed, + * and back using to_bits(). + */ + AMOMIN => to_bits(sizeof(xlen), min(signed(rs2_val), signed(loaded))), + AMOMAX => to_bits(sizeof(xlen), max(signed(rs2_val), signed(loaded))), + AMOMINU => to_bits(sizeof(xlen), min(unsigned(rs2_val), unsigned(loaded))), + AMOMAXU => to_bits(sizeof(xlen), max(unsigned(rs2_val), unsigned(loaded))) + }; + let rval : xlenbits = match width { + BYTE => sign_extend(loaded[7..0]), + HALF => sign_extend(loaded[15..0]), + WORD => sign_extend(loaded[31..0]), + DOUBLE => loaded + }; + let wval : MemoryOpResult(bool) = match (width, sizeof(xlen)) { + (BYTE, _) => mem_write_value(addr, 1, result[7..0], aq & rl, rl, true), + (HALF, _) => mem_write_value(addr, 2, result[15..0], aq & rl, rl, true), + (WORD, _) => mem_write_value(addr, 4, result[31..0], aq & rl, rl, true), + (DOUBLE, 64) => mem_write_value(addr, 8, result, aq & rl, rl, true), + _ => internal_error(__FILE__, __LINE__, "Unexpected AMO width") + }; + match (wval) { + MemValue(true) => { X(rd) = rval; RETIRE_SUCCESS }, + MemValue(false) => { internal_error(__FILE__, __LINE__, "AMO got false from mem_write_value") }, + MemException(e) => { handle_mem_exception(vaddr, e); RETIRE_FAIL } + } + } + } + } + } + } + } + } + } + } else { + handle_illegal(); + RETIRE_FAIL + } + } + +# SPDX-SnippetEnd diff --git a/spec/std/isa/inst/Zabha/amoadd.b.yaml b/spec/std/isa/inst/Zabha/amoadd.b.yaml index 64a7b3d19e..05dbc9bfa1 100644 --- a/spec/std/isa/inst/Zabha/amoadd.b.yaml +++ b/spec/std/isa/inst/Zabha/amoadd.b.yaml @@ -1,4 +1,6 @@ # Copyright (c) Qualcomm Technologies, Inc. and/or its subsidiaries. + +# WARNING: This file is auto-generated from spec/std/isa/inst/Zaamo/amoadd.SIZE.AQRL.layout# Copyright (c) Abhijit Das(Sukuna0007Abhi) # SPDX-License-Identifier: BSD-3-Clause-Clear # yaml-language-server: $schema=../../../../schemas/inst_schema.json @@ -6,18 +8,19 @@ $schema: "inst_schema.json#" kind: instruction name: amoadd.b -long_name: No synopsis available +long_name: Atomic fetch-and-add byte description: | - No description available. + Atomically: + + * Load the byte at address _xs1_ + * Write the sign-extended value into _xd_ + * Add the least-significant byte of register _xs2_ to the loaded value + * Write the result to the address in _xs1_ definedBy: Zabha assembly: xd, xs2, (xs1) encoding: - match: 00000------------000-----0101111 + match: 0000000----------000-----0101111 variables: - - name: aq - location: 26-26 - - name: rl - location: 25-25 - name: xs2 location: 24-20 - name: xs1 @@ -29,8 +32,13 @@ access: u: always vs: always vu: always -data_independent_timing: false operation(): | + if (!implemented?(ExtensionName::A) || (MISA_CSR_IMPLEMENTED && (CSR[misa].A == 1'b0))) { + raise (ExceptionCode::IllegalInstruction, mode(), $encoding); + } + + XReg virtual_address = X[xs1]; + X[xd] = amo<8>(virtual_address, X[xs2][7:0], AmoOperation::Add, 1'b0, 1'b0, $encoding); # SPDX-SnippetBegin # SPDX-FileCopyrightText: 2017-2025 Contributors to the RISCV Sail Model diff --git a/spec/std/isa/inst/Zabha/amoadd.h.aq.yaml b/spec/std/isa/inst/Zabha/amoadd.h.aq.yaml new file mode 100644 index 0000000000..3ddb9dbe4c --- /dev/null +++ b/spec/std/isa/inst/Zabha/amoadd.h.aq.yaml @@ -0,0 +1,139 @@ +# Copyright (c) Qualcomm Technologies, Inc. and/or its subsidiaries. + +# WARNING: This file is auto-generated from spec/std/isa/inst/Zaamo/amoadd.SIZE.AQRL.layout# Copyright (c) Abhijit Das(Sukuna0007Abhi) +# SPDX-License-Identifier: BSD-3-Clause-Clear + +# yaml-language-server: $schema=../../../../schemas/inst_schema.json + +$schema: "inst_schema.json#" +kind: instruction +name: amoadd.h.aq +long_name: Atomic fetch-and-add halfword (acquire) +description: | + Atomically with acquire ordering: + + * Load the halfword at address _xs1_ + * Write the sign-extended value into _xd_ + * Add the least-significant halfword of register _xs2_ to the loaded value + * Write the result to the address in _xs1_ +definedBy: Zabha +assembly: xd, xs2, (xs1) +encoding: + match: 0000010----------001-----0101111 + variables: + - name: xs2 + location: 24-20 + - name: xs1 + location: 19-15 + - name: xd + location: 11-7 +access: + s: always + u: always + vs: always + vu: always +operation(): | + if (!implemented?(ExtensionName::A) || (MISA_CSR_IMPLEMENTED && (CSR[misa].A == 1'b0))) { + raise (ExceptionCode::IllegalInstruction, mode(), $encoding); + } + + memory_model_acquire(); + + XReg virtual_address = X[xs1]; + X[xd] = amo<16>(virtual_address, X[xs2][15:0], AmoOperation::Add, 1'b1, 1'b0, $encoding); + +# SPDX-SnippetBegin +# SPDX-FileCopyrightText: 2017-2025 Contributors to the RISCV Sail Model +# SPDX-License-Identifier: BSD-2-Clause +sail(): | + { + if extension("A") then { + /* Get the address, X(rs1) (no offset). + * Some extensions perform additional checks on address validity. + */ + match ext_data_get_addr(rs1, zeros(), ReadWrite(Data, Data), width) { + Ext_DataAddr_Error(e) => { ext_handle_data_check_error(e); RETIRE_FAIL }, + Ext_DataAddr_OK(vaddr) => { + match translateAddr(vaddr, ReadWrite(Data, Data)) { + TR_Failure(e, _) => { handle_mem_exception(vaddr, e); RETIRE_FAIL }, + TR_Address(addr, _) => { + let eares : MemoryOpResult(unit) = match (width, sizeof(xlen)) { + (BYTE, _) => mem_write_ea(addr, 1, aq & rl, rl, true), + (HALF, _) => mem_write_ea(addr, 2, aq & rl, rl, true), + (WORD, _) => mem_write_ea(addr, 4, aq & rl, rl, true), + (DOUBLE, 64) => mem_write_ea(addr, 8, aq & rl, rl, true), + _ => internal_error(__FILE__, __LINE__, "Unexpected AMO width") + }; + let is_unsigned : bool = match op { + AMOMINU => true, + AMOMAXU => true, + _ => false + }; + let rs2_val : xlenbits = match width { + BYTE => if is_unsigned then zero_extend(X(rs2)[7..0]) else sign_extend(X(rs2)[7..0]), + HALF => if is_unsigned then zero_extend(X(rs2)[15..0]) else sign_extend(X(rs2)[15..0]), + WORD => if is_unsigned then zero_extend(X(rs2)[31..0]) else sign_extend(X(rs2)[31..0]), + DOUBLE => X(rs2) + }; + match (eares) { + MemException(e) => { handle_mem_exception(vaddr, e); RETIRE_FAIL }, + MemValue(_) => { + let mval : MemoryOpResult(xlenbits) = match (width, sizeof(xlen)) { + (BYTE, _) => extend_value(is_unsigned, mem_read(ReadWrite(Data, Data), addr, 1, aq, aq & rl, true)), + (HALF, _) => extend_value(is_unsigned, mem_read(ReadWrite(Data, Data), addr, 2, aq, aq & rl, true)), + (WORD, _) => extend_value(is_unsigned, mem_read(ReadWrite(Data, Data), addr, 4, aq, aq & rl, true)), + (DOUBLE, 64) => extend_value(is_unsigned, mem_read(ReadWrite(Data, Data), addr, 8, aq, aq & rl, true)), + _ => internal_error(__FILE__, __LINE__, "Unexpected AMO width") + }; + match (mval) { + MemException(e) => { handle_mem_exception(vaddr, e); RETIRE_FAIL }, + MemValue(loaded) => { + let result : xlenbits = + match op { + AMOSWAP => rs2_val, + AMOADD => rs2_val + loaded, + AMOXOR => rs2_val ^ loaded, + AMOAND => rs2_val & loaded, + AMOOR => rs2_val | loaded, + + /* These operations convert bitvectors to integer values using [un]signed, + * and back using to_bits(). + */ + AMOMIN => to_bits(sizeof(xlen), min(signed(rs2_val), signed(loaded))), + AMOMAX => to_bits(sizeof(xlen), max(signed(rs2_val), signed(loaded))), + AMOMINU => to_bits(sizeof(xlen), min(unsigned(rs2_val), unsigned(loaded))), + AMOMAXU => to_bits(sizeof(xlen), max(unsigned(rs2_val), unsigned(loaded))) + }; + let rval : xlenbits = match width { + BYTE => sign_extend(loaded[7..0]), + HALF => sign_extend(loaded[15..0]), + WORD => sign_extend(loaded[31..0]), + DOUBLE => loaded + }; + let wval : MemoryOpResult(bool) = match (width, sizeof(xlen)) { + (BYTE, _) => mem_write_value(addr, 1, result[7..0], aq & rl, rl, true), + (HALF, _) => mem_write_value(addr, 2, result[15..0], aq & rl, rl, true), + (WORD, _) => mem_write_value(addr, 4, result[31..0], aq & rl, rl, true), + (DOUBLE, 64) => mem_write_value(addr, 8, result, aq & rl, rl, true), + _ => internal_error(__FILE__, __LINE__, "Unexpected AMO width") + }; + match (wval) { + MemValue(true) => { X(rd) = rval; RETIRE_SUCCESS }, + MemValue(false) => { internal_error(__FILE__, __LINE__, "AMO got false from mem_write_value") }, + MemException(e) => { handle_mem_exception(vaddr, e); RETIRE_FAIL } + } + } + } + } + } + } + } + } + } + } else { + handle_illegal(); + RETIRE_FAIL + } + } + +# SPDX-SnippetEnd diff --git a/spec/std/isa/inst/Zabha/amoadd.h.aqrl.yaml b/spec/std/isa/inst/Zabha/amoadd.h.aqrl.yaml new file mode 100644 index 0000000000..0ad5beaf4e --- /dev/null +++ b/spec/std/isa/inst/Zabha/amoadd.h.aqrl.yaml @@ -0,0 +1,141 @@ +# Copyright (c) Qualcomm Technologies, Inc. and/or its subsidiaries. + +# WARNING: This file is auto-generated from spec/std/isa/inst/Zaamo/amoadd.SIZE.AQRL.layout# Copyright (c) Abhijit Das(Sukuna0007Abhi) +# SPDX-License-Identifier: BSD-3-Clause-Clear + +# yaml-language-server: $schema=../../../../schemas/inst_schema.json + +$schema: "inst_schema.json#" +kind: instruction +name: amoadd.h.aqrl +long_name: Atomic fetch-and-add halfword (acquire-release) +description: | + Atomically with acquire and release ordering: + + * Load the halfword at address _xs1_ + * Write the sign-extended value into _xd_ + * Add the least-significant halfword of register _xs2_ to the loaded value + * Write the result to the address in _xs1_ +definedBy: Zabha +assembly: xd, xs2, (xs1) +encoding: + match: 0000011----------001-----0101111 + variables: + - name: xs2 + location: 24-20 + - name: xs1 + location: 19-15 + - name: xd + location: 11-7 +access: + s: always + u: always + vs: always + vu: always +operation(): | + if (!implemented?(ExtensionName::A) || (MISA_CSR_IMPLEMENTED && (CSR[misa].A == 1'b0))) { + raise (ExceptionCode::IllegalInstruction, mode(), $encoding); + } + + memory_model_acquire(); + + XReg virtual_address = X[xs1]; + X[xd] = amo<16>(virtual_address, X[xs2][15:0], AmoOperation::Add, 1'b1, 1'b1, $encoding); + + memory_model_release(); + +# SPDX-SnippetBegin +# SPDX-FileCopyrightText: 2017-2025 Contributors to the RISCV Sail Model +# SPDX-License-Identifier: BSD-2-Clause +sail(): | + { + if extension("A") then { + /* Get the address, X(rs1) (no offset). + * Some extensions perform additional checks on address validity. + */ + match ext_data_get_addr(rs1, zeros(), ReadWrite(Data, Data), width) { + Ext_DataAddr_Error(e) => { ext_handle_data_check_error(e); RETIRE_FAIL }, + Ext_DataAddr_OK(vaddr) => { + match translateAddr(vaddr, ReadWrite(Data, Data)) { + TR_Failure(e, _) => { handle_mem_exception(vaddr, e); RETIRE_FAIL }, + TR_Address(addr, _) => { + let eares : MemoryOpResult(unit) = match (width, sizeof(xlen)) { + (BYTE, _) => mem_write_ea(addr, 1, aq & rl, rl, true), + (HALF, _) => mem_write_ea(addr, 2, aq & rl, rl, true), + (WORD, _) => mem_write_ea(addr, 4, aq & rl, rl, true), + (DOUBLE, 64) => mem_write_ea(addr, 8, aq & rl, rl, true), + _ => internal_error(__FILE__, __LINE__, "Unexpected AMO width") + }; + let is_unsigned : bool = match op { + AMOMINU => true, + AMOMAXU => true, + _ => false + }; + let rs2_val : xlenbits = match width { + BYTE => if is_unsigned then zero_extend(X(rs2)[7..0]) else sign_extend(X(rs2)[7..0]), + HALF => if is_unsigned then zero_extend(X(rs2)[15..0]) else sign_extend(X(rs2)[15..0]), + WORD => if is_unsigned then zero_extend(X(rs2)[31..0]) else sign_extend(X(rs2)[31..0]), + DOUBLE => X(rs2) + }; + match (eares) { + MemException(e) => { handle_mem_exception(vaddr, e); RETIRE_FAIL }, + MemValue(_) => { + let mval : MemoryOpResult(xlenbits) = match (width, sizeof(xlen)) { + (BYTE, _) => extend_value(is_unsigned, mem_read(ReadWrite(Data, Data), addr, 1, aq, aq & rl, true)), + (HALF, _) => extend_value(is_unsigned, mem_read(ReadWrite(Data, Data), addr, 2, aq, aq & rl, true)), + (WORD, _) => extend_value(is_unsigned, mem_read(ReadWrite(Data, Data), addr, 4, aq, aq & rl, true)), + (DOUBLE, 64) => extend_value(is_unsigned, mem_read(ReadWrite(Data, Data), addr, 8, aq, aq & rl, true)), + _ => internal_error(__FILE__, __LINE__, "Unexpected AMO width") + }; + match (mval) { + MemException(e) => { handle_mem_exception(vaddr, e); RETIRE_FAIL }, + MemValue(loaded) => { + let result : xlenbits = + match op { + AMOSWAP => rs2_val, + AMOADD => rs2_val + loaded, + AMOXOR => rs2_val ^ loaded, + AMOAND => rs2_val & loaded, + AMOOR => rs2_val | loaded, + + /* These operations convert bitvectors to integer values using [un]signed, + * and back using to_bits(). + */ + AMOMIN => to_bits(sizeof(xlen), min(signed(rs2_val), signed(loaded))), + AMOMAX => to_bits(sizeof(xlen), max(signed(rs2_val), signed(loaded))), + AMOMINU => to_bits(sizeof(xlen), min(unsigned(rs2_val), unsigned(loaded))), + AMOMAXU => to_bits(sizeof(xlen), max(unsigned(rs2_val), unsigned(loaded))) + }; + let rval : xlenbits = match width { + BYTE => sign_extend(loaded[7..0]), + HALF => sign_extend(loaded[15..0]), + WORD => sign_extend(loaded[31..0]), + DOUBLE => loaded + }; + let wval : MemoryOpResult(bool) = match (width, sizeof(xlen)) { + (BYTE, _) => mem_write_value(addr, 1, result[7..0], aq & rl, rl, true), + (HALF, _) => mem_write_value(addr, 2, result[15..0], aq & rl, rl, true), + (WORD, _) => mem_write_value(addr, 4, result[31..0], aq & rl, rl, true), + (DOUBLE, 64) => mem_write_value(addr, 8, result, aq & rl, rl, true), + _ => internal_error(__FILE__, __LINE__, "Unexpected AMO width") + }; + match (wval) { + MemValue(true) => { X(rd) = rval; RETIRE_SUCCESS }, + MemValue(false) => { internal_error(__FILE__, __LINE__, "AMO got false from mem_write_value") }, + MemException(e) => { handle_mem_exception(vaddr, e); RETIRE_FAIL } + } + } + } + } + } + } + } + } + } + } else { + handle_illegal(); + RETIRE_FAIL + } + } + +# SPDX-SnippetEnd diff --git a/spec/std/isa/inst/Zabha/amoadd.h.rl.yaml b/spec/std/isa/inst/Zabha/amoadd.h.rl.yaml new file mode 100644 index 0000000000..9e2df43b5e --- /dev/null +++ b/spec/std/isa/inst/Zabha/amoadd.h.rl.yaml @@ -0,0 +1,139 @@ +# Copyright (c) Qualcomm Technologies, Inc. and/or its subsidiaries. + +# WARNING: This file is auto-generated from spec/std/isa/inst/Zaamo/amoadd.SIZE.AQRL.layout# Copyright (c) Abhijit Das(Sukuna0007Abhi) +# SPDX-License-Identifier: BSD-3-Clause-Clear + +# yaml-language-server: $schema=../../../../schemas/inst_schema.json + +$schema: "inst_schema.json#" +kind: instruction +name: amoadd.h.rl +long_name: Atomic fetch-and-add halfword (release) +description: | + Atomically with release ordering: + + * Load the halfword at address _xs1_ + * Write the sign-extended value into _xd_ + * Add the least-significant halfword of register _xs2_ to the loaded value + * Write the result to the address in _xs1_ +definedBy: Zabha +assembly: xd, xs2, (xs1) +encoding: + match: 0000001----------001-----0101111 + variables: + - name: xs2 + location: 24-20 + - name: xs1 + location: 19-15 + - name: xd + location: 11-7 +access: + s: always + u: always + vs: always + vu: always +operation(): | + if (!implemented?(ExtensionName::A) || (MISA_CSR_IMPLEMENTED && (CSR[misa].A == 1'b0))) { + raise (ExceptionCode::IllegalInstruction, mode(), $encoding); + } + + XReg virtual_address = X[xs1]; + X[xd] = amo<16>(virtual_address, X[xs2][15:0], AmoOperation::Add, 1'b0, 1'b1, $encoding); + + memory_model_release(); + +# SPDX-SnippetBegin +# SPDX-FileCopyrightText: 2017-2025 Contributors to the RISCV Sail Model +# SPDX-License-Identifier: BSD-2-Clause +sail(): | + { + if extension("A") then { + /* Get the address, X(rs1) (no offset). + * Some extensions perform additional checks on address validity. + */ + match ext_data_get_addr(rs1, zeros(), ReadWrite(Data, Data), width) { + Ext_DataAddr_Error(e) => { ext_handle_data_check_error(e); RETIRE_FAIL }, + Ext_DataAddr_OK(vaddr) => { + match translateAddr(vaddr, ReadWrite(Data, Data)) { + TR_Failure(e, _) => { handle_mem_exception(vaddr, e); RETIRE_FAIL }, + TR_Address(addr, _) => { + let eares : MemoryOpResult(unit) = match (width, sizeof(xlen)) { + (BYTE, _) => mem_write_ea(addr, 1, aq & rl, rl, true), + (HALF, _) => mem_write_ea(addr, 2, aq & rl, rl, true), + (WORD, _) => mem_write_ea(addr, 4, aq & rl, rl, true), + (DOUBLE, 64) => mem_write_ea(addr, 8, aq & rl, rl, true), + _ => internal_error(__FILE__, __LINE__, "Unexpected AMO width") + }; + let is_unsigned : bool = match op { + AMOMINU => true, + AMOMAXU => true, + _ => false + }; + let rs2_val : xlenbits = match width { + BYTE => if is_unsigned then zero_extend(X(rs2)[7..0]) else sign_extend(X(rs2)[7..0]), + HALF => if is_unsigned then zero_extend(X(rs2)[15..0]) else sign_extend(X(rs2)[15..0]), + WORD => if is_unsigned then zero_extend(X(rs2)[31..0]) else sign_extend(X(rs2)[31..0]), + DOUBLE => X(rs2) + }; + match (eares) { + MemException(e) => { handle_mem_exception(vaddr, e); RETIRE_FAIL }, + MemValue(_) => { + let mval : MemoryOpResult(xlenbits) = match (width, sizeof(xlen)) { + (BYTE, _) => extend_value(is_unsigned, mem_read(ReadWrite(Data, Data), addr, 1, aq, aq & rl, true)), + (HALF, _) => extend_value(is_unsigned, mem_read(ReadWrite(Data, Data), addr, 2, aq, aq & rl, true)), + (WORD, _) => extend_value(is_unsigned, mem_read(ReadWrite(Data, Data), addr, 4, aq, aq & rl, true)), + (DOUBLE, 64) => extend_value(is_unsigned, mem_read(ReadWrite(Data, Data), addr, 8, aq, aq & rl, true)), + _ => internal_error(__FILE__, __LINE__, "Unexpected AMO width") + }; + match (mval) { + MemException(e) => { handle_mem_exception(vaddr, e); RETIRE_FAIL }, + MemValue(loaded) => { + let result : xlenbits = + match op { + AMOSWAP => rs2_val, + AMOADD => rs2_val + loaded, + AMOXOR => rs2_val ^ loaded, + AMOAND => rs2_val & loaded, + AMOOR => rs2_val | loaded, + + /* These operations convert bitvectors to integer values using [un]signed, + * and back using to_bits(). + */ + AMOMIN => to_bits(sizeof(xlen), min(signed(rs2_val), signed(loaded))), + AMOMAX => to_bits(sizeof(xlen), max(signed(rs2_val), signed(loaded))), + AMOMINU => to_bits(sizeof(xlen), min(unsigned(rs2_val), unsigned(loaded))), + AMOMAXU => to_bits(sizeof(xlen), max(unsigned(rs2_val), unsigned(loaded))) + }; + let rval : xlenbits = match width { + BYTE => sign_extend(loaded[7..0]), + HALF => sign_extend(loaded[15..0]), + WORD => sign_extend(loaded[31..0]), + DOUBLE => loaded + }; + let wval : MemoryOpResult(bool) = match (width, sizeof(xlen)) { + (BYTE, _) => mem_write_value(addr, 1, result[7..0], aq & rl, rl, true), + (HALF, _) => mem_write_value(addr, 2, result[15..0], aq & rl, rl, true), + (WORD, _) => mem_write_value(addr, 4, result[31..0], aq & rl, rl, true), + (DOUBLE, 64) => mem_write_value(addr, 8, result, aq & rl, rl, true), + _ => internal_error(__FILE__, __LINE__, "Unexpected AMO width") + }; + match (wval) { + MemValue(true) => { X(rd) = rval; RETIRE_SUCCESS }, + MemValue(false) => { internal_error(__FILE__, __LINE__, "AMO got false from mem_write_value") }, + MemException(e) => { handle_mem_exception(vaddr, e); RETIRE_FAIL } + } + } + } + } + } + } + } + } + } + } else { + handle_illegal(); + RETIRE_FAIL + } + } + +# SPDX-SnippetEnd diff --git a/spec/std/isa/inst/Zabha/amoadd.h.yaml b/spec/std/isa/inst/Zabha/amoadd.h.yaml index 7d585340b1..f9baf31492 100644 --- a/spec/std/isa/inst/Zabha/amoadd.h.yaml +++ b/spec/std/isa/inst/Zabha/amoadd.h.yaml @@ -1,4 +1,6 @@ # Copyright (c) Qualcomm Technologies, Inc. and/or its subsidiaries. + +# WARNING: This file is auto-generated from spec/std/isa/inst/Zaamo/amoadd.SIZE.AQRL.layout# Copyright (c) Abhijit Das(Sukuna0007Abhi) # SPDX-License-Identifier: BSD-3-Clause-Clear # yaml-language-server: $schema=../../../../schemas/inst_schema.json @@ -6,18 +8,19 @@ $schema: "inst_schema.json#" kind: instruction name: amoadd.h -long_name: No synopsis available +long_name: Atomic fetch-and-add halfword description: | - No description available. + Atomically: + + * Load the halfword at address _xs1_ + * Write the sign-extended value into _xd_ + * Add the least-significant halfword of register _xs2_ to the loaded value + * Write the result to the address in _xs1_ definedBy: Zabha assembly: xd, xs2, (xs1) encoding: - match: 00000------------001-----0101111 + match: 0000000----------001-----0101111 variables: - - name: aq - location: 26-26 - - name: rl - location: 25-25 - name: xs2 location: 24-20 - name: xs1 @@ -29,8 +32,13 @@ access: u: always vs: always vu: always -data_independent_timing: false operation(): | + if (!implemented?(ExtensionName::A) || (MISA_CSR_IMPLEMENTED && (CSR[misa].A == 1'b0))) { + raise (ExceptionCode::IllegalInstruction, mode(), $encoding); + } + + XReg virtual_address = X[xs1]; + X[xd] = amo<16>(virtual_address, X[xs2][15:0], AmoOperation::Add, 1'b0, 1'b0, $encoding); # SPDX-SnippetBegin # SPDX-FileCopyrightText: 2017-2025 Contributors to the RISCV Sail Model diff --git a/spec/std/isa/inst/Zabha/amoand.b.aq.yaml b/spec/std/isa/inst/Zabha/amoand.b.aq.yaml new file mode 100644 index 0000000000..cbc4fe0dd6 --- /dev/null +++ b/spec/std/isa/inst/Zabha/amoand.b.aq.yaml @@ -0,0 +1,139 @@ +# Copyright (c) Qualcomm Technologies, Inc. and/or its subsidiaries. + +# WARNING: This file is auto-generated from spec/std/isa/inst/Zaamo/amoand.SIZE.AQRL.layout# Copyright (c) Abhijit Das(Sukuna0007Abhi) +# SPDX-License-Identifier: BSD-3-Clause-Clear + +# yaml-language-server: $schema=../../../../schemas/inst_schema.json + +$schema: "inst_schema.json#" +kind: instruction +name: amoand.b.aq +long_name: Atomic fetch-and-and byte (acquire) +description: | + Atomically with acquire ordering: + + * Load the byte at address _xs1_ + * Write the sign-extended value into _xd_ + * AND the least-significant byte of register _xs2_ to the loaded value + * Write the result to the address in _xs1_ +definedBy: Zabha +assembly: xd, xs2, (xs1) +encoding: + match: 0110010----------000-----0101111 + variables: + - name: xs2 + location: 24-20 + - name: xs1 + location: 19-15 + - name: xd + location: 11-7 +access: + s: always + u: always + vs: always + vu: always +operation(): | + if (!implemented?(ExtensionName::A) || (MISA_CSR_IMPLEMENTED && (CSR[misa].A == 1'b0))) { + raise (ExceptionCode::IllegalInstruction, mode(), $encoding); + } + + memory_model_acquire(); + + XReg virtual_address = X[xs1]; + X[xd] = amo<8>(virtual_address, X[xs2][7:0], AmoOperation::And, 1'b1, 1'b0, $encoding); + +# SPDX-SnippetBegin +# SPDX-FileCopyrightText: 2017-2025 Contributors to the RISCV Sail Model +# SPDX-License-Identifier: BSD-2-Clause +sail(): | + { + if extension("A") then { + /* Get the address, X(rs1) (no offset). + * Some extensions perform additional checks on address validity. + */ + match ext_data_get_addr(rs1, zeros(), ReadWrite(Data, Data), width) { + Ext_DataAddr_Error(e) => { ext_handle_data_check_error(e); RETIRE_FAIL }, + Ext_DataAddr_OK(vaddr) => { + match translateAddr(vaddr, ReadWrite(Data, Data)) { + TR_Failure(e, _) => { handle_mem_exception(vaddr, e); RETIRE_FAIL }, + TR_Address(addr, _) => { + let eares : MemoryOpResult(unit) = match (width, sizeof(xlen)) { + (BYTE, _) => mem_write_ea(addr, 1, aq & rl, rl, true), + (HALF, _) => mem_write_ea(addr, 2, aq & rl, rl, true), + (WORD, _) => mem_write_ea(addr, 4, aq & rl, rl, true), + (DOUBLE, 64) => mem_write_ea(addr, 8, aq & rl, rl, true), + _ => internal_error(__FILE__, __LINE__, "Unexpected AMO width") + }; + let is_unsigned : bool = match op { + AMOMINU => true, + AMOMAXU => true, + _ => false + }; + let rs2_val : xlenbits = match width { + BYTE => if is_unsigned then zero_extend(X(rs2)[7..0]) else sign_extend(X(rs2)[7..0]), + HALF => if is_unsigned then zero_extend(X(rs2)[15..0]) else sign_extend(X(rs2)[15..0]), + WORD => if is_unsigned then zero_extend(X(rs2)[31..0]) else sign_extend(X(rs2)[31..0]), + DOUBLE => X(rs2) + }; + match (eares) { + MemException(e) => { handle_mem_exception(vaddr, e); RETIRE_FAIL }, + MemValue(_) => { + let mval : MemoryOpResult(xlenbits) = match (width, sizeof(xlen)) { + (BYTE, _) => extend_value(is_unsigned, mem_read(ReadWrite(Data, Data), addr, 1, aq, aq & rl, true)), + (HALF, _) => extend_value(is_unsigned, mem_read(ReadWrite(Data, Data), addr, 2, aq, aq & rl, true)), + (WORD, _) => extend_value(is_unsigned, mem_read(ReadWrite(Data, Data), addr, 4, aq, aq & rl, true)), + (DOUBLE, 64) => extend_value(is_unsigned, mem_read(ReadWrite(Data, Data), addr, 8, aq, aq & rl, true)), + _ => internal_error(__FILE__, __LINE__, "Unexpected AMO width") + }; + match (mval) { + MemException(e) => { handle_mem_exception(vaddr, e); RETIRE_FAIL }, + MemValue(loaded) => { + let result : xlenbits = + match op { + AMOSWAP => rs2_val, + AMOADD => rs2_val + loaded, + AMOXOR => rs2_val ^ loaded, + AMOAND => rs2_val & loaded, + AMOOR => rs2_val | loaded, + + /* These operations convert bitvectors to integer values using [un]signed, + * and back using to_bits(). + */ + AMOMIN => to_bits(sizeof(xlen), min(signed(rs2_val), signed(loaded))), + AMOMAX => to_bits(sizeof(xlen), max(signed(rs2_val), signed(loaded))), + AMOMINU => to_bits(sizeof(xlen), min(unsigned(rs2_val), unsigned(loaded))), + AMOMAXU => to_bits(sizeof(xlen), max(unsigned(rs2_val), unsigned(loaded))) + }; + let rval : xlenbits = match width { + BYTE => sign_extend(loaded[7..0]), + HALF => sign_extend(loaded[15..0]), + WORD => sign_extend(loaded[31..0]), + DOUBLE => loaded + }; + let wval : MemoryOpResult(bool) = match (width, sizeof(xlen)) { + (BYTE, _) => mem_write_value(addr, 1, result[7..0], aq & rl, rl, true), + (HALF, _) => mem_write_value(addr, 2, result[15..0], aq & rl, rl, true), + (WORD, _) => mem_write_value(addr, 4, result[31..0], aq & rl, rl, true), + (DOUBLE, 64) => mem_write_value(addr, 8, result, aq & rl, rl, true), + _ => internal_error(__FILE__, __LINE__, "Unexpected AMO width") + }; + match (wval) { + MemValue(true) => { X(rd) = rval; RETIRE_SUCCESS }, + MemValue(false) => { internal_error(__FILE__, __LINE__, "AMO got false from mem_write_value") }, + MemException(e) => { handle_mem_exception(vaddr, e); RETIRE_FAIL } + } + } + } + } + } + } + } + } + } + } else { + handle_illegal(); + RETIRE_FAIL + } + } + +# SPDX-SnippetEnd diff --git a/spec/std/isa/inst/Zabha/amoand.b.aqrl.yaml b/spec/std/isa/inst/Zabha/amoand.b.aqrl.yaml new file mode 100644 index 0000000000..76520c2769 --- /dev/null +++ b/spec/std/isa/inst/Zabha/amoand.b.aqrl.yaml @@ -0,0 +1,141 @@ +# Copyright (c) Qualcomm Technologies, Inc. and/or its subsidiaries. + +# WARNING: This file is auto-generated from spec/std/isa/inst/Zaamo/amoand.SIZE.AQRL.layout# Copyright (c) Abhijit Das(Sukuna0007Abhi) +# SPDX-License-Identifier: BSD-3-Clause-Clear + +# yaml-language-server: $schema=../../../../schemas/inst_schema.json + +$schema: "inst_schema.json#" +kind: instruction +name: amoand.b.aqrl +long_name: Atomic fetch-and-and byte (acquire-release) +description: | + Atomically with acquire and release ordering: + + * Load the byte at address _xs1_ + * Write the sign-extended value into _xd_ + * AND the least-significant byte of register _xs2_ to the loaded value + * Write the result to the address in _xs1_ +definedBy: Zabha +assembly: xd, xs2, (xs1) +encoding: + match: 0110011----------000-----0101111 + variables: + - name: xs2 + location: 24-20 + - name: xs1 + location: 19-15 + - name: xd + location: 11-7 +access: + s: always + u: always + vs: always + vu: always +operation(): | + if (!implemented?(ExtensionName::A) || (MISA_CSR_IMPLEMENTED && (CSR[misa].A == 1'b0))) { + raise (ExceptionCode::IllegalInstruction, mode(), $encoding); + } + + memory_model_acquire(); + + XReg virtual_address = X[xs1]; + X[xd] = amo<8>(virtual_address, X[xs2][7:0], AmoOperation::And, 1'b1, 1'b1, $encoding); + + memory_model_release(); + +# SPDX-SnippetBegin +# SPDX-FileCopyrightText: 2017-2025 Contributors to the RISCV Sail Model +# SPDX-License-Identifier: BSD-2-Clause +sail(): | + { + if extension("A") then { + /* Get the address, X(rs1) (no offset). + * Some extensions perform additional checks on address validity. + */ + match ext_data_get_addr(rs1, zeros(), ReadWrite(Data, Data), width) { + Ext_DataAddr_Error(e) => { ext_handle_data_check_error(e); RETIRE_FAIL }, + Ext_DataAddr_OK(vaddr) => { + match translateAddr(vaddr, ReadWrite(Data, Data)) { + TR_Failure(e, _) => { handle_mem_exception(vaddr, e); RETIRE_FAIL }, + TR_Address(addr, _) => { + let eares : MemoryOpResult(unit) = match (width, sizeof(xlen)) { + (BYTE, _) => mem_write_ea(addr, 1, aq & rl, rl, true), + (HALF, _) => mem_write_ea(addr, 2, aq & rl, rl, true), + (WORD, _) => mem_write_ea(addr, 4, aq & rl, rl, true), + (DOUBLE, 64) => mem_write_ea(addr, 8, aq & rl, rl, true), + _ => internal_error(__FILE__, __LINE__, "Unexpected AMO width") + }; + let is_unsigned : bool = match op { + AMOMINU => true, + AMOMAXU => true, + _ => false + }; + let rs2_val : xlenbits = match width { + BYTE => if is_unsigned then zero_extend(X(rs2)[7..0]) else sign_extend(X(rs2)[7..0]), + HALF => if is_unsigned then zero_extend(X(rs2)[15..0]) else sign_extend(X(rs2)[15..0]), + WORD => if is_unsigned then zero_extend(X(rs2)[31..0]) else sign_extend(X(rs2)[31..0]), + DOUBLE => X(rs2) + }; + match (eares) { + MemException(e) => { handle_mem_exception(vaddr, e); RETIRE_FAIL }, + MemValue(_) => { + let mval : MemoryOpResult(xlenbits) = match (width, sizeof(xlen)) { + (BYTE, _) => extend_value(is_unsigned, mem_read(ReadWrite(Data, Data), addr, 1, aq, aq & rl, true)), + (HALF, _) => extend_value(is_unsigned, mem_read(ReadWrite(Data, Data), addr, 2, aq, aq & rl, true)), + (WORD, _) => extend_value(is_unsigned, mem_read(ReadWrite(Data, Data), addr, 4, aq, aq & rl, true)), + (DOUBLE, 64) => extend_value(is_unsigned, mem_read(ReadWrite(Data, Data), addr, 8, aq, aq & rl, true)), + _ => internal_error(__FILE__, __LINE__, "Unexpected AMO width") + }; + match (mval) { + MemException(e) => { handle_mem_exception(vaddr, e); RETIRE_FAIL }, + MemValue(loaded) => { + let result : xlenbits = + match op { + AMOSWAP => rs2_val, + AMOADD => rs2_val + loaded, + AMOXOR => rs2_val ^ loaded, + AMOAND => rs2_val & loaded, + AMOOR => rs2_val | loaded, + + /* These operations convert bitvectors to integer values using [un]signed, + * and back using to_bits(). + */ + AMOMIN => to_bits(sizeof(xlen), min(signed(rs2_val), signed(loaded))), + AMOMAX => to_bits(sizeof(xlen), max(signed(rs2_val), signed(loaded))), + AMOMINU => to_bits(sizeof(xlen), min(unsigned(rs2_val), unsigned(loaded))), + AMOMAXU => to_bits(sizeof(xlen), max(unsigned(rs2_val), unsigned(loaded))) + }; + let rval : xlenbits = match width { + BYTE => sign_extend(loaded[7..0]), + HALF => sign_extend(loaded[15..0]), + WORD => sign_extend(loaded[31..0]), + DOUBLE => loaded + }; + let wval : MemoryOpResult(bool) = match (width, sizeof(xlen)) { + (BYTE, _) => mem_write_value(addr, 1, result[7..0], aq & rl, rl, true), + (HALF, _) => mem_write_value(addr, 2, result[15..0], aq & rl, rl, true), + (WORD, _) => mem_write_value(addr, 4, result[31..0], aq & rl, rl, true), + (DOUBLE, 64) => mem_write_value(addr, 8, result, aq & rl, rl, true), + _ => internal_error(__FILE__, __LINE__, "Unexpected AMO width") + }; + match (wval) { + MemValue(true) => { X(rd) = rval; RETIRE_SUCCESS }, + MemValue(false) => { internal_error(__FILE__, __LINE__, "AMO got false from mem_write_value") }, + MemException(e) => { handle_mem_exception(vaddr, e); RETIRE_FAIL } + } + } + } + } + } + } + } + } + } + } else { + handle_illegal(); + RETIRE_FAIL + } + } + +# SPDX-SnippetEnd diff --git a/spec/std/isa/inst/Zabha/amoand.b.rl.yaml b/spec/std/isa/inst/Zabha/amoand.b.rl.yaml new file mode 100644 index 0000000000..08a357f948 --- /dev/null +++ b/spec/std/isa/inst/Zabha/amoand.b.rl.yaml @@ -0,0 +1,139 @@ +# Copyright (c) Qualcomm Technologies, Inc. and/or its subsidiaries. + +# WARNING: This file is auto-generated from spec/std/isa/inst/Zaamo/amoand.SIZE.AQRL.layout# Copyright (c) Abhijit Das(Sukuna0007Abhi) +# SPDX-License-Identifier: BSD-3-Clause-Clear + +# yaml-language-server: $schema=../../../../schemas/inst_schema.json + +$schema: "inst_schema.json#" +kind: instruction +name: amoand.b.rl +long_name: Atomic fetch-and-and byte (release) +description: | + Atomically with release ordering: + + * Load the byte at address _xs1_ + * Write the sign-extended value into _xd_ + * AND the least-significant byte of register _xs2_ to the loaded value + * Write the result to the address in _xs1_ +definedBy: Zabha +assembly: xd, xs2, (xs1) +encoding: + match: 0110001----------000-----0101111 + variables: + - name: xs2 + location: 24-20 + - name: xs1 + location: 19-15 + - name: xd + location: 11-7 +access: + s: always + u: always + vs: always + vu: always +operation(): | + if (!implemented?(ExtensionName::A) || (MISA_CSR_IMPLEMENTED && (CSR[misa].A == 1'b0))) { + raise (ExceptionCode::IllegalInstruction, mode(), $encoding); + } + + XReg virtual_address = X[xs1]; + X[xd] = amo<8>(virtual_address, X[xs2][7:0], AmoOperation::And, 1'b0, 1'b1, $encoding); + + memory_model_release(); + +# SPDX-SnippetBegin +# SPDX-FileCopyrightText: 2017-2025 Contributors to the RISCV Sail Model +# SPDX-License-Identifier: BSD-2-Clause +sail(): | + { + if extension("A") then { + /* Get the address, X(rs1) (no offset). + * Some extensions perform additional checks on address validity. + */ + match ext_data_get_addr(rs1, zeros(), ReadWrite(Data, Data), width) { + Ext_DataAddr_Error(e) => { ext_handle_data_check_error(e); RETIRE_FAIL }, + Ext_DataAddr_OK(vaddr) => { + match translateAddr(vaddr, ReadWrite(Data, Data)) { + TR_Failure(e, _) => { handle_mem_exception(vaddr, e); RETIRE_FAIL }, + TR_Address(addr, _) => { + let eares : MemoryOpResult(unit) = match (width, sizeof(xlen)) { + (BYTE, _) => mem_write_ea(addr, 1, aq & rl, rl, true), + (HALF, _) => mem_write_ea(addr, 2, aq & rl, rl, true), + (WORD, _) => mem_write_ea(addr, 4, aq & rl, rl, true), + (DOUBLE, 64) => mem_write_ea(addr, 8, aq & rl, rl, true), + _ => internal_error(__FILE__, __LINE__, "Unexpected AMO width") + }; + let is_unsigned : bool = match op { + AMOMINU => true, + AMOMAXU => true, + _ => false + }; + let rs2_val : xlenbits = match width { + BYTE => if is_unsigned then zero_extend(X(rs2)[7..0]) else sign_extend(X(rs2)[7..0]), + HALF => if is_unsigned then zero_extend(X(rs2)[15..0]) else sign_extend(X(rs2)[15..0]), + WORD => if is_unsigned then zero_extend(X(rs2)[31..0]) else sign_extend(X(rs2)[31..0]), + DOUBLE => X(rs2) + }; + match (eares) { + MemException(e) => { handle_mem_exception(vaddr, e); RETIRE_FAIL }, + MemValue(_) => { + let mval : MemoryOpResult(xlenbits) = match (width, sizeof(xlen)) { + (BYTE, _) => extend_value(is_unsigned, mem_read(ReadWrite(Data, Data), addr, 1, aq, aq & rl, true)), + (HALF, _) => extend_value(is_unsigned, mem_read(ReadWrite(Data, Data), addr, 2, aq, aq & rl, true)), + (WORD, _) => extend_value(is_unsigned, mem_read(ReadWrite(Data, Data), addr, 4, aq, aq & rl, true)), + (DOUBLE, 64) => extend_value(is_unsigned, mem_read(ReadWrite(Data, Data), addr, 8, aq, aq & rl, true)), + _ => internal_error(__FILE__, __LINE__, "Unexpected AMO width") + }; + match (mval) { + MemException(e) => { handle_mem_exception(vaddr, e); RETIRE_FAIL }, + MemValue(loaded) => { + let result : xlenbits = + match op { + AMOSWAP => rs2_val, + AMOADD => rs2_val + loaded, + AMOXOR => rs2_val ^ loaded, + AMOAND => rs2_val & loaded, + AMOOR => rs2_val | loaded, + + /* These operations convert bitvectors to integer values using [un]signed, + * and back using to_bits(). + */ + AMOMIN => to_bits(sizeof(xlen), min(signed(rs2_val), signed(loaded))), + AMOMAX => to_bits(sizeof(xlen), max(signed(rs2_val), signed(loaded))), + AMOMINU => to_bits(sizeof(xlen), min(unsigned(rs2_val), unsigned(loaded))), + AMOMAXU => to_bits(sizeof(xlen), max(unsigned(rs2_val), unsigned(loaded))) + }; + let rval : xlenbits = match width { + BYTE => sign_extend(loaded[7..0]), + HALF => sign_extend(loaded[15..0]), + WORD => sign_extend(loaded[31..0]), + DOUBLE => loaded + }; + let wval : MemoryOpResult(bool) = match (width, sizeof(xlen)) { + (BYTE, _) => mem_write_value(addr, 1, result[7..0], aq & rl, rl, true), + (HALF, _) => mem_write_value(addr, 2, result[15..0], aq & rl, rl, true), + (WORD, _) => mem_write_value(addr, 4, result[31..0], aq & rl, rl, true), + (DOUBLE, 64) => mem_write_value(addr, 8, result, aq & rl, rl, true), + _ => internal_error(__FILE__, __LINE__, "Unexpected AMO width") + }; + match (wval) { + MemValue(true) => { X(rd) = rval; RETIRE_SUCCESS }, + MemValue(false) => { internal_error(__FILE__, __LINE__, "AMO got false from mem_write_value") }, + MemException(e) => { handle_mem_exception(vaddr, e); RETIRE_FAIL } + } + } + } + } + } + } + } + } + } + } else { + handle_illegal(); + RETIRE_FAIL + } + } + +# SPDX-SnippetEnd diff --git a/spec/std/isa/inst/Zabha/amoand.b.yaml b/spec/std/isa/inst/Zabha/amoand.b.yaml index 65c43aa256..16063eb612 100644 --- a/spec/std/isa/inst/Zabha/amoand.b.yaml +++ b/spec/std/isa/inst/Zabha/amoand.b.yaml @@ -1,4 +1,6 @@ # Copyright (c) Qualcomm Technologies, Inc. and/or its subsidiaries. + +# WARNING: This file is auto-generated from spec/std/isa/inst/Zaamo/amoand.SIZE.AQRL.layout# Copyright (c) Abhijit Das(Sukuna0007Abhi) # SPDX-License-Identifier: BSD-3-Clause-Clear # yaml-language-server: $schema=../../../../schemas/inst_schema.json @@ -6,18 +8,19 @@ $schema: "inst_schema.json#" kind: instruction name: amoand.b -long_name: No synopsis available +long_name: Atomic fetch-and-and byte description: | - No description available. + Atomically: + + * Load the byte at address _xs1_ + * Write the sign-extended value into _xd_ + * AND the least-significant byte of register _xs2_ to the loaded value + * Write the result to the address in _xs1_ definedBy: Zabha assembly: xd, xs2, (xs1) encoding: - match: 01100------------000-----0101111 + match: 0110000----------000-----0101111 variables: - - name: aq - location: 26-26 - - name: rl - location: 25-25 - name: xs2 location: 24-20 - name: xs1 @@ -29,8 +32,13 @@ access: u: always vs: always vu: always -data_independent_timing: false operation(): | + if (!implemented?(ExtensionName::A) || (MISA_CSR_IMPLEMENTED && (CSR[misa].A == 1'b0))) { + raise (ExceptionCode::IllegalInstruction, mode(), $encoding); + } + + XReg virtual_address = X[xs1]; + X[xd] = amo<8>(virtual_address, X[xs2][7:0], AmoOperation::And, 1'b0, 1'b0, $encoding); # SPDX-SnippetBegin # SPDX-FileCopyrightText: 2017-2025 Contributors to the RISCV Sail Model diff --git a/spec/std/isa/inst/Zabha/amoand.h.aq.yaml b/spec/std/isa/inst/Zabha/amoand.h.aq.yaml new file mode 100644 index 0000000000..1f2807631e --- /dev/null +++ b/spec/std/isa/inst/Zabha/amoand.h.aq.yaml @@ -0,0 +1,139 @@ +# Copyright (c) Qualcomm Technologies, Inc. and/or its subsidiaries. + +# WARNING: This file is auto-generated from spec/std/isa/inst/Zaamo/amoand.SIZE.AQRL.layout# Copyright (c) Abhijit Das(Sukuna0007Abhi) +# SPDX-License-Identifier: BSD-3-Clause-Clear + +# yaml-language-server: $schema=../../../../schemas/inst_schema.json + +$schema: "inst_schema.json#" +kind: instruction +name: amoand.h.aq +long_name: Atomic fetch-and-and halfword (acquire) +description: | + Atomically with acquire ordering: + + * Load the halfword at address _xs1_ + * Write the sign-extended value into _xd_ + * AND the least-significant halfword of register _xs2_ to the loaded value + * Write the result to the address in _xs1_ +definedBy: Zabha +assembly: xd, xs2, (xs1) +encoding: + match: 0110010----------001-----0101111 + variables: + - name: xs2 + location: 24-20 + - name: xs1 + location: 19-15 + - name: xd + location: 11-7 +access: + s: always + u: always + vs: always + vu: always +operation(): | + if (!implemented?(ExtensionName::A) || (MISA_CSR_IMPLEMENTED && (CSR[misa].A == 1'b0))) { + raise (ExceptionCode::IllegalInstruction, mode(), $encoding); + } + + memory_model_acquire(); + + XReg virtual_address = X[xs1]; + X[xd] = amo<16>(virtual_address, X[xs2][15:0], AmoOperation::And, 1'b1, 1'b0, $encoding); + +# SPDX-SnippetBegin +# SPDX-FileCopyrightText: 2017-2025 Contributors to the RISCV Sail Model +# SPDX-License-Identifier: BSD-2-Clause +sail(): | + { + if extension("A") then { + /* Get the address, X(rs1) (no offset). + * Some extensions perform additional checks on address validity. + */ + match ext_data_get_addr(rs1, zeros(), ReadWrite(Data, Data), width) { + Ext_DataAddr_Error(e) => { ext_handle_data_check_error(e); RETIRE_FAIL }, + Ext_DataAddr_OK(vaddr) => { + match translateAddr(vaddr, ReadWrite(Data, Data)) { + TR_Failure(e, _) => { handle_mem_exception(vaddr, e); RETIRE_FAIL }, + TR_Address(addr, _) => { + let eares : MemoryOpResult(unit) = match (width, sizeof(xlen)) { + (BYTE, _) => mem_write_ea(addr, 1, aq & rl, rl, true), + (HALF, _) => mem_write_ea(addr, 2, aq & rl, rl, true), + (WORD, _) => mem_write_ea(addr, 4, aq & rl, rl, true), + (DOUBLE, 64) => mem_write_ea(addr, 8, aq & rl, rl, true), + _ => internal_error(__FILE__, __LINE__, "Unexpected AMO width") + }; + let is_unsigned : bool = match op { + AMOMINU => true, + AMOMAXU => true, + _ => false + }; + let rs2_val : xlenbits = match width { + BYTE => if is_unsigned then zero_extend(X(rs2)[7..0]) else sign_extend(X(rs2)[7..0]), + HALF => if is_unsigned then zero_extend(X(rs2)[15..0]) else sign_extend(X(rs2)[15..0]), + WORD => if is_unsigned then zero_extend(X(rs2)[31..0]) else sign_extend(X(rs2)[31..0]), + DOUBLE => X(rs2) + }; + match (eares) { + MemException(e) => { handle_mem_exception(vaddr, e); RETIRE_FAIL }, + MemValue(_) => { + let mval : MemoryOpResult(xlenbits) = match (width, sizeof(xlen)) { + (BYTE, _) => extend_value(is_unsigned, mem_read(ReadWrite(Data, Data), addr, 1, aq, aq & rl, true)), + (HALF, _) => extend_value(is_unsigned, mem_read(ReadWrite(Data, Data), addr, 2, aq, aq & rl, true)), + (WORD, _) => extend_value(is_unsigned, mem_read(ReadWrite(Data, Data), addr, 4, aq, aq & rl, true)), + (DOUBLE, 64) => extend_value(is_unsigned, mem_read(ReadWrite(Data, Data), addr, 8, aq, aq & rl, true)), + _ => internal_error(__FILE__, __LINE__, "Unexpected AMO width") + }; + match (mval) { + MemException(e) => { handle_mem_exception(vaddr, e); RETIRE_FAIL }, + MemValue(loaded) => { + let result : xlenbits = + match op { + AMOSWAP => rs2_val, + AMOADD => rs2_val + loaded, + AMOXOR => rs2_val ^ loaded, + AMOAND => rs2_val & loaded, + AMOOR => rs2_val | loaded, + + /* These operations convert bitvectors to integer values using [un]signed, + * and back using to_bits(). + */ + AMOMIN => to_bits(sizeof(xlen), min(signed(rs2_val), signed(loaded))), + AMOMAX => to_bits(sizeof(xlen), max(signed(rs2_val), signed(loaded))), + AMOMINU => to_bits(sizeof(xlen), min(unsigned(rs2_val), unsigned(loaded))), + AMOMAXU => to_bits(sizeof(xlen), max(unsigned(rs2_val), unsigned(loaded))) + }; + let rval : xlenbits = match width { + BYTE => sign_extend(loaded[7..0]), + HALF => sign_extend(loaded[15..0]), + WORD => sign_extend(loaded[31..0]), + DOUBLE => loaded + }; + let wval : MemoryOpResult(bool) = match (width, sizeof(xlen)) { + (BYTE, _) => mem_write_value(addr, 1, result[7..0], aq & rl, rl, true), + (HALF, _) => mem_write_value(addr, 2, result[15..0], aq & rl, rl, true), + (WORD, _) => mem_write_value(addr, 4, result[31..0], aq & rl, rl, true), + (DOUBLE, 64) => mem_write_value(addr, 8, result, aq & rl, rl, true), + _ => internal_error(__FILE__, __LINE__, "Unexpected AMO width") + }; + match (wval) { + MemValue(true) => { X(rd) = rval; RETIRE_SUCCESS }, + MemValue(false) => { internal_error(__FILE__, __LINE__, "AMO got false from mem_write_value") }, + MemException(e) => { handle_mem_exception(vaddr, e); RETIRE_FAIL } + } + } + } + } + } + } + } + } + } + } else { + handle_illegal(); + RETIRE_FAIL + } + } + +# SPDX-SnippetEnd diff --git a/spec/std/isa/inst/Zabha/amoand.h.aqrl.yaml b/spec/std/isa/inst/Zabha/amoand.h.aqrl.yaml new file mode 100644 index 0000000000..6343b0f5f2 --- /dev/null +++ b/spec/std/isa/inst/Zabha/amoand.h.aqrl.yaml @@ -0,0 +1,141 @@ +# Copyright (c) Qualcomm Technologies, Inc. and/or its subsidiaries. + +# WARNING: This file is auto-generated from spec/std/isa/inst/Zaamo/amoand.SIZE.AQRL.layout# Copyright (c) Abhijit Das(Sukuna0007Abhi) +# SPDX-License-Identifier: BSD-3-Clause-Clear + +# yaml-language-server: $schema=../../../../schemas/inst_schema.json + +$schema: "inst_schema.json#" +kind: instruction +name: amoand.h.aqrl +long_name: Atomic fetch-and-and halfword (acquire-release) +description: | + Atomically with acquire and release ordering: + + * Load the halfword at address _xs1_ + * Write the sign-extended value into _xd_ + * AND the least-significant halfword of register _xs2_ to the loaded value + * Write the result to the address in _xs1_ +definedBy: Zabha +assembly: xd, xs2, (xs1) +encoding: + match: 0110011----------001-----0101111 + variables: + - name: xs2 + location: 24-20 + - name: xs1 + location: 19-15 + - name: xd + location: 11-7 +access: + s: always + u: always + vs: always + vu: always +operation(): | + if (!implemented?(ExtensionName::A) || (MISA_CSR_IMPLEMENTED && (CSR[misa].A == 1'b0))) { + raise (ExceptionCode::IllegalInstruction, mode(), $encoding); + } + + memory_model_acquire(); + + XReg virtual_address = X[xs1]; + X[xd] = amo<16>(virtual_address, X[xs2][15:0], AmoOperation::And, 1'b1, 1'b1, $encoding); + + memory_model_release(); + +# SPDX-SnippetBegin +# SPDX-FileCopyrightText: 2017-2025 Contributors to the RISCV Sail Model +# SPDX-License-Identifier: BSD-2-Clause +sail(): | + { + if extension("A") then { + /* Get the address, X(rs1) (no offset). + * Some extensions perform additional checks on address validity. + */ + match ext_data_get_addr(rs1, zeros(), ReadWrite(Data, Data), width) { + Ext_DataAddr_Error(e) => { ext_handle_data_check_error(e); RETIRE_FAIL }, + Ext_DataAddr_OK(vaddr) => { + match translateAddr(vaddr, ReadWrite(Data, Data)) { + TR_Failure(e, _) => { handle_mem_exception(vaddr, e); RETIRE_FAIL }, + TR_Address(addr, _) => { + let eares : MemoryOpResult(unit) = match (width, sizeof(xlen)) { + (BYTE, _) => mem_write_ea(addr, 1, aq & rl, rl, true), + (HALF, _) => mem_write_ea(addr, 2, aq & rl, rl, true), + (WORD, _) => mem_write_ea(addr, 4, aq & rl, rl, true), + (DOUBLE, 64) => mem_write_ea(addr, 8, aq & rl, rl, true), + _ => internal_error(__FILE__, __LINE__, "Unexpected AMO width") + }; + let is_unsigned : bool = match op { + AMOMINU => true, + AMOMAXU => true, + _ => false + }; + let rs2_val : xlenbits = match width { + BYTE => if is_unsigned then zero_extend(X(rs2)[7..0]) else sign_extend(X(rs2)[7..0]), + HALF => if is_unsigned then zero_extend(X(rs2)[15..0]) else sign_extend(X(rs2)[15..0]), + WORD => if is_unsigned then zero_extend(X(rs2)[31..0]) else sign_extend(X(rs2)[31..0]), + DOUBLE => X(rs2) + }; + match (eares) { + MemException(e) => { handle_mem_exception(vaddr, e); RETIRE_FAIL }, + MemValue(_) => { + let mval : MemoryOpResult(xlenbits) = match (width, sizeof(xlen)) { + (BYTE, _) => extend_value(is_unsigned, mem_read(ReadWrite(Data, Data), addr, 1, aq, aq & rl, true)), + (HALF, _) => extend_value(is_unsigned, mem_read(ReadWrite(Data, Data), addr, 2, aq, aq & rl, true)), + (WORD, _) => extend_value(is_unsigned, mem_read(ReadWrite(Data, Data), addr, 4, aq, aq & rl, true)), + (DOUBLE, 64) => extend_value(is_unsigned, mem_read(ReadWrite(Data, Data), addr, 8, aq, aq & rl, true)), + _ => internal_error(__FILE__, __LINE__, "Unexpected AMO width") + }; + match (mval) { + MemException(e) => { handle_mem_exception(vaddr, e); RETIRE_FAIL }, + MemValue(loaded) => { + let result : xlenbits = + match op { + AMOSWAP => rs2_val, + AMOADD => rs2_val + loaded, + AMOXOR => rs2_val ^ loaded, + AMOAND => rs2_val & loaded, + AMOOR => rs2_val | loaded, + + /* These operations convert bitvectors to integer values using [un]signed, + * and back using to_bits(). + */ + AMOMIN => to_bits(sizeof(xlen), min(signed(rs2_val), signed(loaded))), + AMOMAX => to_bits(sizeof(xlen), max(signed(rs2_val), signed(loaded))), + AMOMINU => to_bits(sizeof(xlen), min(unsigned(rs2_val), unsigned(loaded))), + AMOMAXU => to_bits(sizeof(xlen), max(unsigned(rs2_val), unsigned(loaded))) + }; + let rval : xlenbits = match width { + BYTE => sign_extend(loaded[7..0]), + HALF => sign_extend(loaded[15..0]), + WORD => sign_extend(loaded[31..0]), + DOUBLE => loaded + }; + let wval : MemoryOpResult(bool) = match (width, sizeof(xlen)) { + (BYTE, _) => mem_write_value(addr, 1, result[7..0], aq & rl, rl, true), + (HALF, _) => mem_write_value(addr, 2, result[15..0], aq & rl, rl, true), + (WORD, _) => mem_write_value(addr, 4, result[31..0], aq & rl, rl, true), + (DOUBLE, 64) => mem_write_value(addr, 8, result, aq & rl, rl, true), + _ => internal_error(__FILE__, __LINE__, "Unexpected AMO width") + }; + match (wval) { + MemValue(true) => { X(rd) = rval; RETIRE_SUCCESS }, + MemValue(false) => { internal_error(__FILE__, __LINE__, "AMO got false from mem_write_value") }, + MemException(e) => { handle_mem_exception(vaddr, e); RETIRE_FAIL } + } + } + } + } + } + } + } + } + } + } else { + handle_illegal(); + RETIRE_FAIL + } + } + +# SPDX-SnippetEnd diff --git a/spec/std/isa/inst/Zabha/amoand.h.rl.yaml b/spec/std/isa/inst/Zabha/amoand.h.rl.yaml new file mode 100644 index 0000000000..7dd1ab3169 --- /dev/null +++ b/spec/std/isa/inst/Zabha/amoand.h.rl.yaml @@ -0,0 +1,139 @@ +# Copyright (c) Qualcomm Technologies, Inc. and/or its subsidiaries. + +# WARNING: This file is auto-generated from spec/std/isa/inst/Zaamo/amoand.SIZE.AQRL.layout# Copyright (c) Abhijit Das(Sukuna0007Abhi) +# SPDX-License-Identifier: BSD-3-Clause-Clear + +# yaml-language-server: $schema=../../../../schemas/inst_schema.json + +$schema: "inst_schema.json#" +kind: instruction +name: amoand.h.rl +long_name: Atomic fetch-and-and halfword (release) +description: | + Atomically with release ordering: + + * Load the halfword at address _xs1_ + * Write the sign-extended value into _xd_ + * AND the least-significant halfword of register _xs2_ to the loaded value + * Write the result to the address in _xs1_ +definedBy: Zabha +assembly: xd, xs2, (xs1) +encoding: + match: 0110001----------001-----0101111 + variables: + - name: xs2 + location: 24-20 + - name: xs1 + location: 19-15 + - name: xd + location: 11-7 +access: + s: always + u: always + vs: always + vu: always +operation(): | + if (!implemented?(ExtensionName::A) || (MISA_CSR_IMPLEMENTED && (CSR[misa].A == 1'b0))) { + raise (ExceptionCode::IllegalInstruction, mode(), $encoding); + } + + XReg virtual_address = X[xs1]; + X[xd] = amo<16>(virtual_address, X[xs2][15:0], AmoOperation::And, 1'b0, 1'b1, $encoding); + + memory_model_release(); + +# SPDX-SnippetBegin +# SPDX-FileCopyrightText: 2017-2025 Contributors to the RISCV Sail Model +# SPDX-License-Identifier: BSD-2-Clause +sail(): | + { + if extension("A") then { + /* Get the address, X(rs1) (no offset). + * Some extensions perform additional checks on address validity. + */ + match ext_data_get_addr(rs1, zeros(), ReadWrite(Data, Data), width) { + Ext_DataAddr_Error(e) => { ext_handle_data_check_error(e); RETIRE_FAIL }, + Ext_DataAddr_OK(vaddr) => { + match translateAddr(vaddr, ReadWrite(Data, Data)) { + TR_Failure(e, _) => { handle_mem_exception(vaddr, e); RETIRE_FAIL }, + TR_Address(addr, _) => { + let eares : MemoryOpResult(unit) = match (width, sizeof(xlen)) { + (BYTE, _) => mem_write_ea(addr, 1, aq & rl, rl, true), + (HALF, _) => mem_write_ea(addr, 2, aq & rl, rl, true), + (WORD, _) => mem_write_ea(addr, 4, aq & rl, rl, true), + (DOUBLE, 64) => mem_write_ea(addr, 8, aq & rl, rl, true), + _ => internal_error(__FILE__, __LINE__, "Unexpected AMO width") + }; + let is_unsigned : bool = match op { + AMOMINU => true, + AMOMAXU => true, + _ => false + }; + let rs2_val : xlenbits = match width { + BYTE => if is_unsigned then zero_extend(X(rs2)[7..0]) else sign_extend(X(rs2)[7..0]), + HALF => if is_unsigned then zero_extend(X(rs2)[15..0]) else sign_extend(X(rs2)[15..0]), + WORD => if is_unsigned then zero_extend(X(rs2)[31..0]) else sign_extend(X(rs2)[31..0]), + DOUBLE => X(rs2) + }; + match (eares) { + MemException(e) => { handle_mem_exception(vaddr, e); RETIRE_FAIL }, + MemValue(_) => { + let mval : MemoryOpResult(xlenbits) = match (width, sizeof(xlen)) { + (BYTE, _) => extend_value(is_unsigned, mem_read(ReadWrite(Data, Data), addr, 1, aq, aq & rl, true)), + (HALF, _) => extend_value(is_unsigned, mem_read(ReadWrite(Data, Data), addr, 2, aq, aq & rl, true)), + (WORD, _) => extend_value(is_unsigned, mem_read(ReadWrite(Data, Data), addr, 4, aq, aq & rl, true)), + (DOUBLE, 64) => extend_value(is_unsigned, mem_read(ReadWrite(Data, Data), addr, 8, aq, aq & rl, true)), + _ => internal_error(__FILE__, __LINE__, "Unexpected AMO width") + }; + match (mval) { + MemException(e) => { handle_mem_exception(vaddr, e); RETIRE_FAIL }, + MemValue(loaded) => { + let result : xlenbits = + match op { + AMOSWAP => rs2_val, + AMOADD => rs2_val + loaded, + AMOXOR => rs2_val ^ loaded, + AMOAND => rs2_val & loaded, + AMOOR => rs2_val | loaded, + + /* These operations convert bitvectors to integer values using [un]signed, + * and back using to_bits(). + */ + AMOMIN => to_bits(sizeof(xlen), min(signed(rs2_val), signed(loaded))), + AMOMAX => to_bits(sizeof(xlen), max(signed(rs2_val), signed(loaded))), + AMOMINU => to_bits(sizeof(xlen), min(unsigned(rs2_val), unsigned(loaded))), + AMOMAXU => to_bits(sizeof(xlen), max(unsigned(rs2_val), unsigned(loaded))) + }; + let rval : xlenbits = match width { + BYTE => sign_extend(loaded[7..0]), + HALF => sign_extend(loaded[15..0]), + WORD => sign_extend(loaded[31..0]), + DOUBLE => loaded + }; + let wval : MemoryOpResult(bool) = match (width, sizeof(xlen)) { + (BYTE, _) => mem_write_value(addr, 1, result[7..0], aq & rl, rl, true), + (HALF, _) => mem_write_value(addr, 2, result[15..0], aq & rl, rl, true), + (WORD, _) => mem_write_value(addr, 4, result[31..0], aq & rl, rl, true), + (DOUBLE, 64) => mem_write_value(addr, 8, result, aq & rl, rl, true), + _ => internal_error(__FILE__, __LINE__, "Unexpected AMO width") + }; + match (wval) { + MemValue(true) => { X(rd) = rval; RETIRE_SUCCESS }, + MemValue(false) => { internal_error(__FILE__, __LINE__, "AMO got false from mem_write_value") }, + MemException(e) => { handle_mem_exception(vaddr, e); RETIRE_FAIL } + } + } + } + } + } + } + } + } + } + } else { + handle_illegal(); + RETIRE_FAIL + } + } + +# SPDX-SnippetEnd diff --git a/spec/std/isa/inst/Zabha/amoand.h.yaml b/spec/std/isa/inst/Zabha/amoand.h.yaml index fa1d82ed78..6b43c5d15a 100644 --- a/spec/std/isa/inst/Zabha/amoand.h.yaml +++ b/spec/std/isa/inst/Zabha/amoand.h.yaml @@ -1,4 +1,6 @@ # Copyright (c) Qualcomm Technologies, Inc. and/or its subsidiaries. + +# WARNING: This file is auto-generated from spec/std/isa/inst/Zaamo/amoand.SIZE.AQRL.layout# Copyright (c) Abhijit Das(Sukuna0007Abhi) # SPDX-License-Identifier: BSD-3-Clause-Clear # yaml-language-server: $schema=../../../../schemas/inst_schema.json @@ -6,18 +8,19 @@ $schema: "inst_schema.json#" kind: instruction name: amoand.h -long_name: No synopsis available +long_name: Atomic fetch-and-and halfword description: | - No description available. + Atomically: + + * Load the halfword at address _xs1_ + * Write the sign-extended value into _xd_ + * AND the least-significant halfword of register _xs2_ to the loaded value + * Write the result to the address in _xs1_ definedBy: Zabha assembly: xd, xs2, (xs1) encoding: - match: 01100------------001-----0101111 + match: 0110000----------001-----0101111 variables: - - name: aq - location: 26-26 - - name: rl - location: 25-25 - name: xs2 location: 24-20 - name: xs1 @@ -29,8 +32,13 @@ access: u: always vs: always vu: always -data_independent_timing: false operation(): | + if (!implemented?(ExtensionName::A) || (MISA_CSR_IMPLEMENTED && (CSR[misa].A == 1'b0))) { + raise (ExceptionCode::IllegalInstruction, mode(), $encoding); + } + + XReg virtual_address = X[xs1]; + X[xd] = amo<16>(virtual_address, X[xs2][15:0], AmoOperation::And, 1'b0, 1'b0, $encoding); # SPDX-SnippetBegin # SPDX-FileCopyrightText: 2017-2025 Contributors to the RISCV Sail Model diff --git a/spec/std/isa/inst/Zabha/amocas.b.aq.yaml b/spec/std/isa/inst/Zabha/amocas.b.aq.yaml new file mode 100644 index 0000000000..61dc188d41 --- /dev/null +++ b/spec/std/isa/inst/Zabha/amocas.b.aq.yaml @@ -0,0 +1,131 @@ +# Copyright (c) Qualcomm Technologies, Inc. and/or its subsidiaries. + +# WARNING: This file is auto-generated from spec/std/isa/inst/Zacas/amocas.SIZE.AQRL.layout# Copyright (c) Abhijit Das(Sukuna0007Abhi) +# SPDX-License-Identifier: BSD-3-Clause-Clear + +# yaml-language-server: $schema=../../../../schemas/inst_schema.json + +$schema: "inst_schema.json#" +kind: instruction +name: amocas.b.aq +long_name: Atomic compare-and-swap byte (acquire) +description: | + Atomically with acquire ordering: + + * Load the byte at address _xs1_ + * Write the sign-extended value into _xd_ + * Compare the loaded value with the least-significant byte of register _xs2_ + * If equal, write the least-significant byte of register _xs2+1_ to the address in _xs1_ +definedBy: Zabha +assembly: xd, xs2, (xs1) +encoding: + match: 0010110----------000-----0101111 + variables: + - name: xs2 + location: 24-20 + - name: xs1 + location: 19-15 + - name: xd + location: 11-7 +access: + s: always + u: always + vs: always + vu: always +operation(): | + if (!implemented?(ExtensionName::Zabha)) { + raise (ExceptionCode::IllegalInstruction, mode(), $encoding); + } + + memory_model_acquire(); + + XReg virtual_address = X[xs1]; + # TODO + # X[xd] = amocas8(virtual_address, X[xs2][7:0], X[xd][7:0], 1'b1, 1'b0, $encoding); + +# SPDX-SnippetBegin +# SPDX-FileCopyrightText: 2017-2025 Contributors to the RISCV Sail Model +# SPDX-License-Identifier: BSD-2-Clause +sail(): | + { + if extension("Zabha") then { + /* Get the address, X(rs1) (no offset). + * Some extensions perform additional checks on address validity. + */ + match ext_data_get_addr(rs1, zeros(), ReadWrite(Data, Data), width) { + Ext_DataAddr_Error(e) => { ext_handle_data_check_error(e); RETIRE_FAIL }, + Ext_DataAddr_OK(vaddr) => { + match translateAddr(vaddr, ReadWrite(Data, Data)) { + TR_Failure(e, _) => { handle_mem_exception(vaddr, e); RETIRE_FAIL }, + TR_Address(addr, _) => { + let eares : MemoryOpResult(unit) = match (width, sizeof(xlen)) { + (BYTE, _) => mem_write_ea(addr, 1, aq & rl, rl, true), + (HALF, _) => mem_write_ea(addr, 2, aq & rl, rl, true), + (WORD, _) => mem_write_ea(addr, 4, aq & rl, rl, true), + (DOUBLE, 64) => mem_write_ea(addr, 8, aq & rl, rl, true), + _ => internal_error(__FILE__, __LINE__, "Unexpected AMOCAS width") + }; + let rs2_val : xlenbits = match width { + BYTE => sign_extend(X(rs2)[7..0]), + HALF => sign_extend(X(rs2)[15..0]), + WORD => sign_extend(X(rs2)[31..0]), + DOUBLE => X(rs2) + }; + let rd_val : xlenbits = match width { + BYTE => sign_extend(X(rd)[7..0]), + HALF => sign_extend(X(rd)[15..0]), + WORD => sign_extend(X(rd)[31..0]), + DOUBLE => X(rd) + }; + match (eares) { + MemException(e) => { handle_mem_exception(vaddr, e); RETIRE_FAIL }, + MemValue(_) => { + let mval : MemoryOpResult(xlenbits) = match (width, sizeof(xlen)) { + (BYTE, _) => extend_value(false, mem_read(ReadWrite(Data, Data), addr, 1, aq, aq & rl, true)), + (HALF, _) => extend_value(false, mem_read(ReadWrite(Data, Data), addr, 2, aq, aq & rl, true)), + (WORD, _) => extend_value(false, mem_read(ReadWrite(Data, Data), addr, 4, aq, aq & rl, true)), + (DOUBLE, 64) => extend_value(false, mem_read(ReadWrite(Data, Data), addr, 8, aq, aq & rl, true)), + _ => internal_error(__FILE__, __LINE__, "Unexpected AMOCAS width") + }; + match (mval) { + MemException(e) => { handle_mem_exception(vaddr, e); RETIRE_FAIL }, + MemValue(loaded) => { + let success : bool = (loaded == rs2_val); + let result : xlenbits = if success then rd_val else loaded; + let rval : xlenbits = match width { + BYTE => sign_extend(loaded[7..0]), + HALF => sign_extend(loaded[15..0]), + WORD => sign_extend(loaded[31..0]), + DOUBLE => loaded + }; + let wval : MemoryOpResult(bool) = if success then { + match (width, sizeof(xlen)) { + (BYTE, _) => mem_write_value(addr, 1, result[7..0], aq & rl, rl, true), + (HALF, _) => mem_write_value(addr, 2, result[15..0], aq & rl, rl, true), + (WORD, _) => mem_write_value(addr, 4, result[31..0], aq & rl, rl, true), + (DOUBLE, 64) => mem_write_value(addr, 8, result, aq & rl, rl, true), + _ => internal_error(__FILE__, __LINE__, "Unexpected AMOCAS width") + } + } else { + MemValue(true) /* No write on compare failure */ + }; + match (wval) { + MemValue(true) => { X(rd) = rval; RETIRE_SUCCESS }, + MemValue(false) => { internal_error(__FILE__, __LINE__, "AMOCAS got false from mem_write_value") }, + MemException(e) => { handle_mem_exception(vaddr, e); RETIRE_FAIL } + } + } + } + } + } + } + } + } + } + } else { + handle_illegal(); + RETIRE_FAIL + } + } + +# SPDX-SnippetEnd diff --git a/spec/std/isa/inst/Zabha/amocas.b.aqrl.yaml b/spec/std/isa/inst/Zabha/amocas.b.aqrl.yaml new file mode 100644 index 0000000000..9aa70f79d6 --- /dev/null +++ b/spec/std/isa/inst/Zabha/amocas.b.aqrl.yaml @@ -0,0 +1,133 @@ +# Copyright (c) Qualcomm Technologies, Inc. and/or its subsidiaries. + +# WARNING: This file is auto-generated from spec/std/isa/inst/Zacas/amocas.SIZE.AQRL.layout# Copyright (c) Abhijit Das(Sukuna0007Abhi) +# SPDX-License-Identifier: BSD-3-Clause-Clear + +# yaml-language-server: $schema=../../../../schemas/inst_schema.json + +$schema: "inst_schema.json#" +kind: instruction +name: amocas.b.aqrl +long_name: Atomic compare-and-swap byte (acquire-release) +description: | + Atomically with acquire and release ordering: + + * Load the byte at address _xs1_ + * Write the sign-extended value into _xd_ + * Compare the loaded value with the least-significant byte of register _xs2_ + * If equal, write the least-significant byte of register _xs2+1_ to the address in _xs1_ +definedBy: Zabha +assembly: xd, xs2, (xs1) +encoding: + match: 0010111----------000-----0101111 + variables: + - name: xs2 + location: 24-20 + - name: xs1 + location: 19-15 + - name: xd + location: 11-7 +access: + s: always + u: always + vs: always + vu: always +operation(): | + if (!implemented?(ExtensionName::Zabha)) { + raise (ExceptionCode::IllegalInstruction, mode(), $encoding); + } + + memory_model_acquire(); + + XReg virtual_address = X[xs1]; + # TODO + # X[xd] = amocas8(virtual_address, X[xs2][7:0], X[xd][7:0], 1'b1, 1'b1, $encoding); + + memory_model_release(); + +# SPDX-SnippetBegin +# SPDX-FileCopyrightText: 2017-2025 Contributors to the RISCV Sail Model +# SPDX-License-Identifier: BSD-2-Clause +sail(): | + { + if extension("Zabha") then { + /* Get the address, X(rs1) (no offset). + * Some extensions perform additional checks on address validity. + */ + match ext_data_get_addr(rs1, zeros(), ReadWrite(Data, Data), width) { + Ext_DataAddr_Error(e) => { ext_handle_data_check_error(e); RETIRE_FAIL }, + Ext_DataAddr_OK(vaddr) => { + match translateAddr(vaddr, ReadWrite(Data, Data)) { + TR_Failure(e, _) => { handle_mem_exception(vaddr, e); RETIRE_FAIL }, + TR_Address(addr, _) => { + let eares : MemoryOpResult(unit) = match (width, sizeof(xlen)) { + (BYTE, _) => mem_write_ea(addr, 1, aq & rl, rl, true), + (HALF, _) => mem_write_ea(addr, 2, aq & rl, rl, true), + (WORD, _) => mem_write_ea(addr, 4, aq & rl, rl, true), + (DOUBLE, 64) => mem_write_ea(addr, 8, aq & rl, rl, true), + _ => internal_error(__FILE__, __LINE__, "Unexpected AMOCAS width") + }; + let rs2_val : xlenbits = match width { + BYTE => sign_extend(X(rs2)[7..0]), + HALF => sign_extend(X(rs2)[15..0]), + WORD => sign_extend(X(rs2)[31..0]), + DOUBLE => X(rs2) + }; + let rd_val : xlenbits = match width { + BYTE => sign_extend(X(rd)[7..0]), + HALF => sign_extend(X(rd)[15..0]), + WORD => sign_extend(X(rd)[31..0]), + DOUBLE => X(rd) + }; + match (eares) { + MemException(e) => { handle_mem_exception(vaddr, e); RETIRE_FAIL }, + MemValue(_) => { + let mval : MemoryOpResult(xlenbits) = match (width, sizeof(xlen)) { + (BYTE, _) => extend_value(false, mem_read(ReadWrite(Data, Data), addr, 1, aq, aq & rl, true)), + (HALF, _) => extend_value(false, mem_read(ReadWrite(Data, Data), addr, 2, aq, aq & rl, true)), + (WORD, _) => extend_value(false, mem_read(ReadWrite(Data, Data), addr, 4, aq, aq & rl, true)), + (DOUBLE, 64) => extend_value(false, mem_read(ReadWrite(Data, Data), addr, 8, aq, aq & rl, true)), + _ => internal_error(__FILE__, __LINE__, "Unexpected AMOCAS width") + }; + match (mval) { + MemException(e) => { handle_mem_exception(vaddr, e); RETIRE_FAIL }, + MemValue(loaded) => { + let success : bool = (loaded == rs2_val); + let result : xlenbits = if success then rd_val else loaded; + let rval : xlenbits = match width { + BYTE => sign_extend(loaded[7..0]), + HALF => sign_extend(loaded[15..0]), + WORD => sign_extend(loaded[31..0]), + DOUBLE => loaded + }; + let wval : MemoryOpResult(bool) = if success then { + match (width, sizeof(xlen)) { + (BYTE, _) => mem_write_value(addr, 1, result[7..0], aq & rl, rl, true), + (HALF, _) => mem_write_value(addr, 2, result[15..0], aq & rl, rl, true), + (WORD, _) => mem_write_value(addr, 4, result[31..0], aq & rl, rl, true), + (DOUBLE, 64) => mem_write_value(addr, 8, result, aq & rl, rl, true), + _ => internal_error(__FILE__, __LINE__, "Unexpected AMOCAS width") + } + } else { + MemValue(true) /* No write on compare failure */ + }; + match (wval) { + MemValue(true) => { X(rd) = rval; RETIRE_SUCCESS }, + MemValue(false) => { internal_error(__FILE__, __LINE__, "AMOCAS got false from mem_write_value") }, + MemException(e) => { handle_mem_exception(vaddr, e); RETIRE_FAIL } + } + } + } + } + } + } + } + } + } + } else { + handle_illegal(); + RETIRE_FAIL + } + } + +# SPDX-SnippetEnd diff --git a/spec/std/isa/inst/Zabha/amocas.b.rl.yaml b/spec/std/isa/inst/Zabha/amocas.b.rl.yaml new file mode 100644 index 0000000000..a20b999e4d --- /dev/null +++ b/spec/std/isa/inst/Zabha/amocas.b.rl.yaml @@ -0,0 +1,131 @@ +# Copyright (c) Qualcomm Technologies, Inc. and/or its subsidiaries. + +# WARNING: This file is auto-generated from spec/std/isa/inst/Zacas/amocas.SIZE.AQRL.layout# Copyright (c) Abhijit Das(Sukuna0007Abhi) +# SPDX-License-Identifier: BSD-3-Clause-Clear + +# yaml-language-server: $schema=../../../../schemas/inst_schema.json + +$schema: "inst_schema.json#" +kind: instruction +name: amocas.b.rl +long_name: Atomic compare-and-swap byte (release) +description: | + Atomically with release ordering: + + * Load the byte at address _xs1_ + * Write the sign-extended value into _xd_ + * Compare the loaded value with the least-significant byte of register _xs2_ + * If equal, write the least-significant byte of register _xs2+1_ to the address in _xs1_ +definedBy: Zabha +assembly: xd, xs2, (xs1) +encoding: + match: 0010101----------000-----0101111 + variables: + - name: xs2 + location: 24-20 + - name: xs1 + location: 19-15 + - name: xd + location: 11-7 +access: + s: always + u: always + vs: always + vu: always +operation(): | + if (!implemented?(ExtensionName::Zabha)) { + raise (ExceptionCode::IllegalInstruction, mode(), $encoding); + } + + XReg virtual_address = X[xs1]; + # TODO + # X[xd] = amocas8(virtual_address, X[xs2][7:0], X[xd][7:0], 1'b0, 1'b1, $encoding); + + memory_model_release(); + +# SPDX-SnippetBegin +# SPDX-FileCopyrightText: 2017-2025 Contributors to the RISCV Sail Model +# SPDX-License-Identifier: BSD-2-Clause +sail(): | + { + if extension("Zabha") then { + /* Get the address, X(rs1) (no offset). + * Some extensions perform additional checks on address validity. + */ + match ext_data_get_addr(rs1, zeros(), ReadWrite(Data, Data), width) { + Ext_DataAddr_Error(e) => { ext_handle_data_check_error(e); RETIRE_FAIL }, + Ext_DataAddr_OK(vaddr) => { + match translateAddr(vaddr, ReadWrite(Data, Data)) { + TR_Failure(e, _) => { handle_mem_exception(vaddr, e); RETIRE_FAIL }, + TR_Address(addr, _) => { + let eares : MemoryOpResult(unit) = match (width, sizeof(xlen)) { + (BYTE, _) => mem_write_ea(addr, 1, aq & rl, rl, true), + (HALF, _) => mem_write_ea(addr, 2, aq & rl, rl, true), + (WORD, _) => mem_write_ea(addr, 4, aq & rl, rl, true), + (DOUBLE, 64) => mem_write_ea(addr, 8, aq & rl, rl, true), + _ => internal_error(__FILE__, __LINE__, "Unexpected AMOCAS width") + }; + let rs2_val : xlenbits = match width { + BYTE => sign_extend(X(rs2)[7..0]), + HALF => sign_extend(X(rs2)[15..0]), + WORD => sign_extend(X(rs2)[31..0]), + DOUBLE => X(rs2) + }; + let rd_val : xlenbits = match width { + BYTE => sign_extend(X(rd)[7..0]), + HALF => sign_extend(X(rd)[15..0]), + WORD => sign_extend(X(rd)[31..0]), + DOUBLE => X(rd) + }; + match (eares) { + MemException(e) => { handle_mem_exception(vaddr, e); RETIRE_FAIL }, + MemValue(_) => { + let mval : MemoryOpResult(xlenbits) = match (width, sizeof(xlen)) { + (BYTE, _) => extend_value(false, mem_read(ReadWrite(Data, Data), addr, 1, aq, aq & rl, true)), + (HALF, _) => extend_value(false, mem_read(ReadWrite(Data, Data), addr, 2, aq, aq & rl, true)), + (WORD, _) => extend_value(false, mem_read(ReadWrite(Data, Data), addr, 4, aq, aq & rl, true)), + (DOUBLE, 64) => extend_value(false, mem_read(ReadWrite(Data, Data), addr, 8, aq, aq & rl, true)), + _ => internal_error(__FILE__, __LINE__, "Unexpected AMOCAS width") + }; + match (mval) { + MemException(e) => { handle_mem_exception(vaddr, e); RETIRE_FAIL }, + MemValue(loaded) => { + let success : bool = (loaded == rs2_val); + let result : xlenbits = if success then rd_val else loaded; + let rval : xlenbits = match width { + BYTE => sign_extend(loaded[7..0]), + HALF => sign_extend(loaded[15..0]), + WORD => sign_extend(loaded[31..0]), + DOUBLE => loaded + }; + let wval : MemoryOpResult(bool) = if success then { + match (width, sizeof(xlen)) { + (BYTE, _) => mem_write_value(addr, 1, result[7..0], aq & rl, rl, true), + (HALF, _) => mem_write_value(addr, 2, result[15..0], aq & rl, rl, true), + (WORD, _) => mem_write_value(addr, 4, result[31..0], aq & rl, rl, true), + (DOUBLE, 64) => mem_write_value(addr, 8, result, aq & rl, rl, true), + _ => internal_error(__FILE__, __LINE__, "Unexpected AMOCAS width") + } + } else { + MemValue(true) /* No write on compare failure */ + }; + match (wval) { + MemValue(true) => { X(rd) = rval; RETIRE_SUCCESS }, + MemValue(false) => { internal_error(__FILE__, __LINE__, "AMOCAS got false from mem_write_value") }, + MemException(e) => { handle_mem_exception(vaddr, e); RETIRE_FAIL } + } + } + } + } + } + } + } + } + } + } else { + handle_illegal(); + RETIRE_FAIL + } + } + +# SPDX-SnippetEnd diff --git a/spec/std/isa/inst/Zabha/amocas.b.yaml b/spec/std/isa/inst/Zabha/amocas.b.yaml index f9f87b9466..54a16628de 100644 --- a/spec/std/isa/inst/Zabha/amocas.b.yaml +++ b/spec/std/isa/inst/Zabha/amocas.b.yaml @@ -1,4 +1,6 @@ # Copyright (c) Qualcomm Technologies, Inc. and/or its subsidiaries. + +# WARNING: This file is auto-generated from spec/std/isa/inst/Zacas/amocas.SIZE.AQRL.layout# Copyright (c) Abhijit Das(Sukuna0007Abhi) # SPDX-License-Identifier: BSD-3-Clause-Clear # yaml-language-server: $schema=../../../../schemas/inst_schema.json @@ -6,18 +8,19 @@ $schema: "inst_schema.json#" kind: instruction name: amocas.b -long_name: No synopsis available +long_name: Atomic compare-and-swap byte description: | - No description available. + Atomically: + + * Load the byte at address _xs1_ + * Write the sign-extended value into _xd_ + * Compare the loaded value with the least-significant byte of register _xs2_ + * If equal, write the least-significant byte of register _xs2+1_ to the address in _xs1_ definedBy: Zabha assembly: xd, xs2, (xs1) encoding: - match: 00101------------000-----0101111 + match: 0010100----------000-----0101111 variables: - - name: aq - location: 26-26 - - name: rl - location: 25-25 - name: xs2 location: 24-20 - name: xs1 @@ -29,5 +32,98 @@ access: u: always vs: always vu: always -data_independent_timing: false operation(): | + if (!implemented?(ExtensionName::Zabha)) { + raise (ExceptionCode::IllegalInstruction, mode(), $encoding); + } + + XReg virtual_address = X[xs1]; + # TODO + # X[xd] = amocas8(virtual_address, X[xs2][7:0], X[xd][7:0], 1'b0, 1'b0, $encoding); + +# SPDX-SnippetBegin +# SPDX-FileCopyrightText: 2017-2025 Contributors to the RISCV Sail Model +# SPDX-License-Identifier: BSD-2-Clause +sail(): | + { + if extension("Zabha") then { + /* Get the address, X(rs1) (no offset). + * Some extensions perform additional checks on address validity. + */ + match ext_data_get_addr(rs1, zeros(), ReadWrite(Data, Data), width) { + Ext_DataAddr_Error(e) => { ext_handle_data_check_error(e); RETIRE_FAIL }, + Ext_DataAddr_OK(vaddr) => { + match translateAddr(vaddr, ReadWrite(Data, Data)) { + TR_Failure(e, _) => { handle_mem_exception(vaddr, e); RETIRE_FAIL }, + TR_Address(addr, _) => { + let eares : MemoryOpResult(unit) = match (width, sizeof(xlen)) { + (BYTE, _) => mem_write_ea(addr, 1, aq & rl, rl, true), + (HALF, _) => mem_write_ea(addr, 2, aq & rl, rl, true), + (WORD, _) => mem_write_ea(addr, 4, aq & rl, rl, true), + (DOUBLE, 64) => mem_write_ea(addr, 8, aq & rl, rl, true), + _ => internal_error(__FILE__, __LINE__, "Unexpected AMOCAS width") + }; + let rs2_val : xlenbits = match width { + BYTE => sign_extend(X(rs2)[7..0]), + HALF => sign_extend(X(rs2)[15..0]), + WORD => sign_extend(X(rs2)[31..0]), + DOUBLE => X(rs2) + }; + let rd_val : xlenbits = match width { + BYTE => sign_extend(X(rd)[7..0]), + HALF => sign_extend(X(rd)[15..0]), + WORD => sign_extend(X(rd)[31..0]), + DOUBLE => X(rd) + }; + match (eares) { + MemException(e) => { handle_mem_exception(vaddr, e); RETIRE_FAIL }, + MemValue(_) => { + let mval : MemoryOpResult(xlenbits) = match (width, sizeof(xlen)) { + (BYTE, _) => extend_value(false, mem_read(ReadWrite(Data, Data), addr, 1, aq, aq & rl, true)), + (HALF, _) => extend_value(false, mem_read(ReadWrite(Data, Data), addr, 2, aq, aq & rl, true)), + (WORD, _) => extend_value(false, mem_read(ReadWrite(Data, Data), addr, 4, aq, aq & rl, true)), + (DOUBLE, 64) => extend_value(false, mem_read(ReadWrite(Data, Data), addr, 8, aq, aq & rl, true)), + _ => internal_error(__FILE__, __LINE__, "Unexpected AMOCAS width") + }; + match (mval) { + MemException(e) => { handle_mem_exception(vaddr, e); RETIRE_FAIL }, + MemValue(loaded) => { + let success : bool = (loaded == rs2_val); + let result : xlenbits = if success then rd_val else loaded; + let rval : xlenbits = match width { + BYTE => sign_extend(loaded[7..0]), + HALF => sign_extend(loaded[15..0]), + WORD => sign_extend(loaded[31..0]), + DOUBLE => loaded + }; + let wval : MemoryOpResult(bool) = if success then { + match (width, sizeof(xlen)) { + (BYTE, _) => mem_write_value(addr, 1, result[7..0], aq & rl, rl, true), + (HALF, _) => mem_write_value(addr, 2, result[15..0], aq & rl, rl, true), + (WORD, _) => mem_write_value(addr, 4, result[31..0], aq & rl, rl, true), + (DOUBLE, 64) => mem_write_value(addr, 8, result, aq & rl, rl, true), + _ => internal_error(__FILE__, __LINE__, "Unexpected AMOCAS width") + } + } else { + MemValue(true) /* No write on compare failure */ + }; + match (wval) { + MemValue(true) => { X(rd) = rval; RETIRE_SUCCESS }, + MemValue(false) => { internal_error(__FILE__, __LINE__, "AMOCAS got false from mem_write_value") }, + MemException(e) => { handle_mem_exception(vaddr, e); RETIRE_FAIL } + } + } + } + } + } + } + } + } + } + } else { + handle_illegal(); + RETIRE_FAIL + } + } + +# SPDX-SnippetEnd diff --git a/spec/std/isa/inst/Zabha/amocas.h.aq.yaml b/spec/std/isa/inst/Zabha/amocas.h.aq.yaml new file mode 100644 index 0000000000..bbc38c1686 --- /dev/null +++ b/spec/std/isa/inst/Zabha/amocas.h.aq.yaml @@ -0,0 +1,131 @@ +# Copyright (c) Qualcomm Technologies, Inc. and/or its subsidiaries. + +# WARNING: This file is auto-generated from spec/std/isa/inst/Zacas/amocas.SIZE.AQRL.layout# Copyright (c) Abhijit Das(Sukuna0007Abhi) +# SPDX-License-Identifier: BSD-3-Clause-Clear + +# yaml-language-server: $schema=../../../../schemas/inst_schema.json + +$schema: "inst_schema.json#" +kind: instruction +name: amocas.h.aq +long_name: Atomic compare-and-swap halfword (acquire) +description: | + Atomically with acquire ordering: + + * Load the halfword at address _xs1_ + * Write the sign-extended value into _xd_ + * Compare the loaded value with the least-significant halfword of register _xs2_ + * If equal, write the least-significant halfword of register _xs2+1_ to the address in _xs1_ +definedBy: Zabha +assembly: xd, xs2, (xs1) +encoding: + match: 0010110----------001-----0101111 + variables: + - name: xs2 + location: 24-20 + - name: xs1 + location: 19-15 + - name: xd + location: 11-7 +access: + s: always + u: always + vs: always + vu: always +operation(): | + if (!implemented?(ExtensionName::Zabha)) { + raise (ExceptionCode::IllegalInstruction, mode(), $encoding); + } + + memory_model_acquire(); + + XReg virtual_address = X[xs1]; + # TODO + # X[xd] = amocas16(virtual_address, X[xs2][15:0], X[xd][15:0], 1'b1, 1'b0, $encoding); + +# SPDX-SnippetBegin +# SPDX-FileCopyrightText: 2017-2025 Contributors to the RISCV Sail Model +# SPDX-License-Identifier: BSD-2-Clause +sail(): | + { + if extension("Zabha") then { + /* Get the address, X(rs1) (no offset). + * Some extensions perform additional checks on address validity. + */ + match ext_data_get_addr(rs1, zeros(), ReadWrite(Data, Data), width) { + Ext_DataAddr_Error(e) => { ext_handle_data_check_error(e); RETIRE_FAIL }, + Ext_DataAddr_OK(vaddr) => { + match translateAddr(vaddr, ReadWrite(Data, Data)) { + TR_Failure(e, _) => { handle_mem_exception(vaddr, e); RETIRE_FAIL }, + TR_Address(addr, _) => { + let eares : MemoryOpResult(unit) = match (width, sizeof(xlen)) { + (BYTE, _) => mem_write_ea(addr, 1, aq & rl, rl, true), + (HALF, _) => mem_write_ea(addr, 2, aq & rl, rl, true), + (WORD, _) => mem_write_ea(addr, 4, aq & rl, rl, true), + (DOUBLE, 64) => mem_write_ea(addr, 8, aq & rl, rl, true), + _ => internal_error(__FILE__, __LINE__, "Unexpected AMOCAS width") + }; + let rs2_val : xlenbits = match width { + BYTE => sign_extend(X(rs2)[7..0]), + HALF => sign_extend(X(rs2)[15..0]), + WORD => sign_extend(X(rs2)[31..0]), + DOUBLE => X(rs2) + }; + let rd_val : xlenbits = match width { + BYTE => sign_extend(X(rd)[7..0]), + HALF => sign_extend(X(rd)[15..0]), + WORD => sign_extend(X(rd)[31..0]), + DOUBLE => X(rd) + }; + match (eares) { + MemException(e) => { handle_mem_exception(vaddr, e); RETIRE_FAIL }, + MemValue(_) => { + let mval : MemoryOpResult(xlenbits) = match (width, sizeof(xlen)) { + (BYTE, _) => extend_value(false, mem_read(ReadWrite(Data, Data), addr, 1, aq, aq & rl, true)), + (HALF, _) => extend_value(false, mem_read(ReadWrite(Data, Data), addr, 2, aq, aq & rl, true)), + (WORD, _) => extend_value(false, mem_read(ReadWrite(Data, Data), addr, 4, aq, aq & rl, true)), + (DOUBLE, 64) => extend_value(false, mem_read(ReadWrite(Data, Data), addr, 8, aq, aq & rl, true)), + _ => internal_error(__FILE__, __LINE__, "Unexpected AMOCAS width") + }; + match (mval) { + MemException(e) => { handle_mem_exception(vaddr, e); RETIRE_FAIL }, + MemValue(loaded) => { + let success : bool = (loaded == rs2_val); + let result : xlenbits = if success then rd_val else loaded; + let rval : xlenbits = match width { + BYTE => sign_extend(loaded[7..0]), + HALF => sign_extend(loaded[15..0]), + WORD => sign_extend(loaded[31..0]), + DOUBLE => loaded + }; + let wval : MemoryOpResult(bool) = if success then { + match (width, sizeof(xlen)) { + (BYTE, _) => mem_write_value(addr, 1, result[7..0], aq & rl, rl, true), + (HALF, _) => mem_write_value(addr, 2, result[15..0], aq & rl, rl, true), + (WORD, _) => mem_write_value(addr, 4, result[31..0], aq & rl, rl, true), + (DOUBLE, 64) => mem_write_value(addr, 8, result, aq & rl, rl, true), + _ => internal_error(__FILE__, __LINE__, "Unexpected AMOCAS width") + } + } else { + MemValue(true) /* No write on compare failure */ + }; + match (wval) { + MemValue(true) => { X(rd) = rval; RETIRE_SUCCESS }, + MemValue(false) => { internal_error(__FILE__, __LINE__, "AMOCAS got false from mem_write_value") }, + MemException(e) => { handle_mem_exception(vaddr, e); RETIRE_FAIL } + } + } + } + } + } + } + } + } + } + } else { + handle_illegal(); + RETIRE_FAIL + } + } + +# SPDX-SnippetEnd diff --git a/spec/std/isa/inst/Zabha/amocas.h.aqrl.yaml b/spec/std/isa/inst/Zabha/amocas.h.aqrl.yaml new file mode 100644 index 0000000000..075d755d5a --- /dev/null +++ b/spec/std/isa/inst/Zabha/amocas.h.aqrl.yaml @@ -0,0 +1,133 @@ +# Copyright (c) Qualcomm Technologies, Inc. and/or its subsidiaries. + +# WARNING: This file is auto-generated from spec/std/isa/inst/Zacas/amocas.SIZE.AQRL.layout# Copyright (c) Abhijit Das(Sukuna0007Abhi) +# SPDX-License-Identifier: BSD-3-Clause-Clear + +# yaml-language-server: $schema=../../../../schemas/inst_schema.json + +$schema: "inst_schema.json#" +kind: instruction +name: amocas.h.aqrl +long_name: Atomic compare-and-swap halfword (acquire-release) +description: | + Atomically with acquire and release ordering: + + * Load the halfword at address _xs1_ + * Write the sign-extended value into _xd_ + * Compare the loaded value with the least-significant halfword of register _xs2_ + * If equal, write the least-significant halfword of register _xs2+1_ to the address in _xs1_ +definedBy: Zabha +assembly: xd, xs2, (xs1) +encoding: + match: 0010111----------001-----0101111 + variables: + - name: xs2 + location: 24-20 + - name: xs1 + location: 19-15 + - name: xd + location: 11-7 +access: + s: always + u: always + vs: always + vu: always +operation(): | + if (!implemented?(ExtensionName::Zabha)) { + raise (ExceptionCode::IllegalInstruction, mode(), $encoding); + } + + memory_model_acquire(); + + XReg virtual_address = X[xs1]; + # TODO + # X[xd] = amocas16(virtual_address, X[xs2][15:0], X[xd][15:0], 1'b1, 1'b1, $encoding); + + memory_model_release(); + +# SPDX-SnippetBegin +# SPDX-FileCopyrightText: 2017-2025 Contributors to the RISCV Sail Model +# SPDX-License-Identifier: BSD-2-Clause +sail(): | + { + if extension("Zabha") then { + /* Get the address, X(rs1) (no offset). + * Some extensions perform additional checks on address validity. + */ + match ext_data_get_addr(rs1, zeros(), ReadWrite(Data, Data), width) { + Ext_DataAddr_Error(e) => { ext_handle_data_check_error(e); RETIRE_FAIL }, + Ext_DataAddr_OK(vaddr) => { + match translateAddr(vaddr, ReadWrite(Data, Data)) { + TR_Failure(e, _) => { handle_mem_exception(vaddr, e); RETIRE_FAIL }, + TR_Address(addr, _) => { + let eares : MemoryOpResult(unit) = match (width, sizeof(xlen)) { + (BYTE, _) => mem_write_ea(addr, 1, aq & rl, rl, true), + (HALF, _) => mem_write_ea(addr, 2, aq & rl, rl, true), + (WORD, _) => mem_write_ea(addr, 4, aq & rl, rl, true), + (DOUBLE, 64) => mem_write_ea(addr, 8, aq & rl, rl, true), + _ => internal_error(__FILE__, __LINE__, "Unexpected AMOCAS width") + }; + let rs2_val : xlenbits = match width { + BYTE => sign_extend(X(rs2)[7..0]), + HALF => sign_extend(X(rs2)[15..0]), + WORD => sign_extend(X(rs2)[31..0]), + DOUBLE => X(rs2) + }; + let rd_val : xlenbits = match width { + BYTE => sign_extend(X(rd)[7..0]), + HALF => sign_extend(X(rd)[15..0]), + WORD => sign_extend(X(rd)[31..0]), + DOUBLE => X(rd) + }; + match (eares) { + MemException(e) => { handle_mem_exception(vaddr, e); RETIRE_FAIL }, + MemValue(_) => { + let mval : MemoryOpResult(xlenbits) = match (width, sizeof(xlen)) { + (BYTE, _) => extend_value(false, mem_read(ReadWrite(Data, Data), addr, 1, aq, aq & rl, true)), + (HALF, _) => extend_value(false, mem_read(ReadWrite(Data, Data), addr, 2, aq, aq & rl, true)), + (WORD, _) => extend_value(false, mem_read(ReadWrite(Data, Data), addr, 4, aq, aq & rl, true)), + (DOUBLE, 64) => extend_value(false, mem_read(ReadWrite(Data, Data), addr, 8, aq, aq & rl, true)), + _ => internal_error(__FILE__, __LINE__, "Unexpected AMOCAS width") + }; + match (mval) { + MemException(e) => { handle_mem_exception(vaddr, e); RETIRE_FAIL }, + MemValue(loaded) => { + let success : bool = (loaded == rs2_val); + let result : xlenbits = if success then rd_val else loaded; + let rval : xlenbits = match width { + BYTE => sign_extend(loaded[7..0]), + HALF => sign_extend(loaded[15..0]), + WORD => sign_extend(loaded[31..0]), + DOUBLE => loaded + }; + let wval : MemoryOpResult(bool) = if success then { + match (width, sizeof(xlen)) { + (BYTE, _) => mem_write_value(addr, 1, result[7..0], aq & rl, rl, true), + (HALF, _) => mem_write_value(addr, 2, result[15..0], aq & rl, rl, true), + (WORD, _) => mem_write_value(addr, 4, result[31..0], aq & rl, rl, true), + (DOUBLE, 64) => mem_write_value(addr, 8, result, aq & rl, rl, true), + _ => internal_error(__FILE__, __LINE__, "Unexpected AMOCAS width") + } + } else { + MemValue(true) /* No write on compare failure */ + }; + match (wval) { + MemValue(true) => { X(rd) = rval; RETIRE_SUCCESS }, + MemValue(false) => { internal_error(__FILE__, __LINE__, "AMOCAS got false from mem_write_value") }, + MemException(e) => { handle_mem_exception(vaddr, e); RETIRE_FAIL } + } + } + } + } + } + } + } + } + } + } else { + handle_illegal(); + RETIRE_FAIL + } + } + +# SPDX-SnippetEnd diff --git a/spec/std/isa/inst/Zabha/amocas.h.rl.yaml b/spec/std/isa/inst/Zabha/amocas.h.rl.yaml new file mode 100644 index 0000000000..386fa3728e --- /dev/null +++ b/spec/std/isa/inst/Zabha/amocas.h.rl.yaml @@ -0,0 +1,131 @@ +# Copyright (c) Qualcomm Technologies, Inc. and/or its subsidiaries. + +# WARNING: This file is auto-generated from spec/std/isa/inst/Zacas/amocas.SIZE.AQRL.layout# Copyright (c) Abhijit Das(Sukuna0007Abhi) +# SPDX-License-Identifier: BSD-3-Clause-Clear + +# yaml-language-server: $schema=../../../../schemas/inst_schema.json + +$schema: "inst_schema.json#" +kind: instruction +name: amocas.h.rl +long_name: Atomic compare-and-swap halfword (release) +description: | + Atomically with release ordering: + + * Load the halfword at address _xs1_ + * Write the sign-extended value into _xd_ + * Compare the loaded value with the least-significant halfword of register _xs2_ + * If equal, write the least-significant halfword of register _xs2+1_ to the address in _xs1_ +definedBy: Zabha +assembly: xd, xs2, (xs1) +encoding: + match: 0010101----------001-----0101111 + variables: + - name: xs2 + location: 24-20 + - name: xs1 + location: 19-15 + - name: xd + location: 11-7 +access: + s: always + u: always + vs: always + vu: always +operation(): | + if (!implemented?(ExtensionName::Zabha)) { + raise (ExceptionCode::IllegalInstruction, mode(), $encoding); + } + + XReg virtual_address = X[xs1]; + # TODO + # X[xd] = amocas16(virtual_address, X[xs2][15:0], X[xd][15:0], 1'b0, 1'b1, $encoding); + + memory_model_release(); + +# SPDX-SnippetBegin +# SPDX-FileCopyrightText: 2017-2025 Contributors to the RISCV Sail Model +# SPDX-License-Identifier: BSD-2-Clause +sail(): | + { + if extension("Zabha") then { + /* Get the address, X(rs1) (no offset). + * Some extensions perform additional checks on address validity. + */ + match ext_data_get_addr(rs1, zeros(), ReadWrite(Data, Data), width) { + Ext_DataAddr_Error(e) => { ext_handle_data_check_error(e); RETIRE_FAIL }, + Ext_DataAddr_OK(vaddr) => { + match translateAddr(vaddr, ReadWrite(Data, Data)) { + TR_Failure(e, _) => { handle_mem_exception(vaddr, e); RETIRE_FAIL }, + TR_Address(addr, _) => { + let eares : MemoryOpResult(unit) = match (width, sizeof(xlen)) { + (BYTE, _) => mem_write_ea(addr, 1, aq & rl, rl, true), + (HALF, _) => mem_write_ea(addr, 2, aq & rl, rl, true), + (WORD, _) => mem_write_ea(addr, 4, aq & rl, rl, true), + (DOUBLE, 64) => mem_write_ea(addr, 8, aq & rl, rl, true), + _ => internal_error(__FILE__, __LINE__, "Unexpected AMOCAS width") + }; + let rs2_val : xlenbits = match width { + BYTE => sign_extend(X(rs2)[7..0]), + HALF => sign_extend(X(rs2)[15..0]), + WORD => sign_extend(X(rs2)[31..0]), + DOUBLE => X(rs2) + }; + let rd_val : xlenbits = match width { + BYTE => sign_extend(X(rd)[7..0]), + HALF => sign_extend(X(rd)[15..0]), + WORD => sign_extend(X(rd)[31..0]), + DOUBLE => X(rd) + }; + match (eares) { + MemException(e) => { handle_mem_exception(vaddr, e); RETIRE_FAIL }, + MemValue(_) => { + let mval : MemoryOpResult(xlenbits) = match (width, sizeof(xlen)) { + (BYTE, _) => extend_value(false, mem_read(ReadWrite(Data, Data), addr, 1, aq, aq & rl, true)), + (HALF, _) => extend_value(false, mem_read(ReadWrite(Data, Data), addr, 2, aq, aq & rl, true)), + (WORD, _) => extend_value(false, mem_read(ReadWrite(Data, Data), addr, 4, aq, aq & rl, true)), + (DOUBLE, 64) => extend_value(false, mem_read(ReadWrite(Data, Data), addr, 8, aq, aq & rl, true)), + _ => internal_error(__FILE__, __LINE__, "Unexpected AMOCAS width") + }; + match (mval) { + MemException(e) => { handle_mem_exception(vaddr, e); RETIRE_FAIL }, + MemValue(loaded) => { + let success : bool = (loaded == rs2_val); + let result : xlenbits = if success then rd_val else loaded; + let rval : xlenbits = match width { + BYTE => sign_extend(loaded[7..0]), + HALF => sign_extend(loaded[15..0]), + WORD => sign_extend(loaded[31..0]), + DOUBLE => loaded + }; + let wval : MemoryOpResult(bool) = if success then { + match (width, sizeof(xlen)) { + (BYTE, _) => mem_write_value(addr, 1, result[7..0], aq & rl, rl, true), + (HALF, _) => mem_write_value(addr, 2, result[15..0], aq & rl, rl, true), + (WORD, _) => mem_write_value(addr, 4, result[31..0], aq & rl, rl, true), + (DOUBLE, 64) => mem_write_value(addr, 8, result, aq & rl, rl, true), + _ => internal_error(__FILE__, __LINE__, "Unexpected AMOCAS width") + } + } else { + MemValue(true) /* No write on compare failure */ + }; + match (wval) { + MemValue(true) => { X(rd) = rval; RETIRE_SUCCESS }, + MemValue(false) => { internal_error(__FILE__, __LINE__, "AMOCAS got false from mem_write_value") }, + MemException(e) => { handle_mem_exception(vaddr, e); RETIRE_FAIL } + } + } + } + } + } + } + } + } + } + } else { + handle_illegal(); + RETIRE_FAIL + } + } + +# SPDX-SnippetEnd diff --git a/spec/std/isa/inst/Zabha/amocas.h.yaml b/spec/std/isa/inst/Zabha/amocas.h.yaml index d0f67040d7..afb868b3ba 100644 --- a/spec/std/isa/inst/Zabha/amocas.h.yaml +++ b/spec/std/isa/inst/Zabha/amocas.h.yaml @@ -1,4 +1,6 @@ # Copyright (c) Qualcomm Technologies, Inc. and/or its subsidiaries. + +# WARNING: This file is auto-generated from spec/std/isa/inst/Zacas/amocas.SIZE.AQRL.layout# Copyright (c) Abhijit Das(Sukuna0007Abhi) # SPDX-License-Identifier: BSD-3-Clause-Clear # yaml-language-server: $schema=../../../../schemas/inst_schema.json @@ -6,18 +8,19 @@ $schema: "inst_schema.json#" kind: instruction name: amocas.h -long_name: No synopsis available +long_name: Atomic compare-and-swap halfword description: | - No description available. + Atomically: + + * Load the halfword at address _xs1_ + * Write the sign-extended value into _xd_ + * Compare the loaded value with the least-significant halfword of register _xs2_ + * If equal, write the least-significant halfword of register _xs2+1_ to the address in _xs1_ definedBy: Zabha assembly: xd, xs2, (xs1) encoding: - match: 00101------------001-----0101111 + match: 0010100----------001-----0101111 variables: - - name: aq - location: 26-26 - - name: rl - location: 25-25 - name: xs2 location: 24-20 - name: xs1 @@ -29,5 +32,98 @@ access: u: always vs: always vu: always -data_independent_timing: false operation(): | + if (!implemented?(ExtensionName::Zabha)) { + raise (ExceptionCode::IllegalInstruction, mode(), $encoding); + } + + XReg virtual_address = X[xs1]; + # TODO + # X[xd] = amocas16(virtual_address, X[xs2][15:0], X[xd][15:0], 1'b0, 1'b0, $encoding); + +# SPDX-SnippetBegin +# SPDX-FileCopyrightText: 2017-2025 Contributors to the RISCV Sail Model +# SPDX-License-Identifier: BSD-2-Clause +sail(): | + { + if extension("Zabha") then { + /* Get the address, X(rs1) (no offset). + * Some extensions perform additional checks on address validity. + */ + match ext_data_get_addr(rs1, zeros(), ReadWrite(Data, Data), width) { + Ext_DataAddr_Error(e) => { ext_handle_data_check_error(e); RETIRE_FAIL }, + Ext_DataAddr_OK(vaddr) => { + match translateAddr(vaddr, ReadWrite(Data, Data)) { + TR_Failure(e, _) => { handle_mem_exception(vaddr, e); RETIRE_FAIL }, + TR_Address(addr, _) => { + let eares : MemoryOpResult(unit) = match (width, sizeof(xlen)) { + (BYTE, _) => mem_write_ea(addr, 1, aq & rl, rl, true), + (HALF, _) => mem_write_ea(addr, 2, aq & rl, rl, true), + (WORD, _) => mem_write_ea(addr, 4, aq & rl, rl, true), + (DOUBLE, 64) => mem_write_ea(addr, 8, aq & rl, rl, true), + _ => internal_error(__FILE__, __LINE__, "Unexpected AMOCAS width") + }; + let rs2_val : xlenbits = match width { + BYTE => sign_extend(X(rs2)[7..0]), + HALF => sign_extend(X(rs2)[15..0]), + WORD => sign_extend(X(rs2)[31..0]), + DOUBLE => X(rs2) + }; + let rd_val : xlenbits = match width { + BYTE => sign_extend(X(rd)[7..0]), + HALF => sign_extend(X(rd)[15..0]), + WORD => sign_extend(X(rd)[31..0]), + DOUBLE => X(rd) + }; + match (eares) { + MemException(e) => { handle_mem_exception(vaddr, e); RETIRE_FAIL }, + MemValue(_) => { + let mval : MemoryOpResult(xlenbits) = match (width, sizeof(xlen)) { + (BYTE, _) => extend_value(false, mem_read(ReadWrite(Data, Data), addr, 1, aq, aq & rl, true)), + (HALF, _) => extend_value(false, mem_read(ReadWrite(Data, Data), addr, 2, aq, aq & rl, true)), + (WORD, _) => extend_value(false, mem_read(ReadWrite(Data, Data), addr, 4, aq, aq & rl, true)), + (DOUBLE, 64) => extend_value(false, mem_read(ReadWrite(Data, Data), addr, 8, aq, aq & rl, true)), + _ => internal_error(__FILE__, __LINE__, "Unexpected AMOCAS width") + }; + match (mval) { + MemException(e) => { handle_mem_exception(vaddr, e); RETIRE_FAIL }, + MemValue(loaded) => { + let success : bool = (loaded == rs2_val); + let result : xlenbits = if success then rd_val else loaded; + let rval : xlenbits = match width { + BYTE => sign_extend(loaded[7..0]), + HALF => sign_extend(loaded[15..0]), + WORD => sign_extend(loaded[31..0]), + DOUBLE => loaded + }; + let wval : MemoryOpResult(bool) = if success then { + match (width, sizeof(xlen)) { + (BYTE, _) => mem_write_value(addr, 1, result[7..0], aq & rl, rl, true), + (HALF, _) => mem_write_value(addr, 2, result[15..0], aq & rl, rl, true), + (WORD, _) => mem_write_value(addr, 4, result[31..0], aq & rl, rl, true), + (DOUBLE, 64) => mem_write_value(addr, 8, result, aq & rl, rl, true), + _ => internal_error(__FILE__, __LINE__, "Unexpected AMOCAS width") + } + } else { + MemValue(true) /* No write on compare failure */ + }; + match (wval) { + MemValue(true) => { X(rd) = rval; RETIRE_SUCCESS }, + MemValue(false) => { internal_error(__FILE__, __LINE__, "AMOCAS got false from mem_write_value") }, + MemException(e) => { handle_mem_exception(vaddr, e); RETIRE_FAIL } + } + } + } + } + } + } + } + } + } + } else { + handle_illegal(); + RETIRE_FAIL + } + } + +# SPDX-SnippetEnd diff --git a/spec/std/isa/inst/Zabha/amomax.b.aq.yaml b/spec/std/isa/inst/Zabha/amomax.b.aq.yaml new file mode 100644 index 0000000000..7baf70b570 --- /dev/null +++ b/spec/std/isa/inst/Zabha/amomax.b.aq.yaml @@ -0,0 +1,139 @@ +# Copyright (c) Qualcomm Technologies, Inc. and/or its subsidiaries. + +# WARNING: This file is auto-generated from spec/std/isa/inst/Zaamo/amomax.SIZE.AQRL.layout# Copyright (c) Abhijit Das(Sukuna0007Abhi) +# SPDX-License-Identifier: BSD-3-Clause-Clear + +# yaml-language-server: $schema=../../../../schemas/inst_schema.json + +$schema: "inst_schema.json#" +kind: instruction +name: amomax.b.aq +long_name: Atomic MAX byte (acquire) +description: | + Atomically with acquire ordering: + + * Load the byte at address _xs1_ + * Write the sign-extended value into _xd_ + * Signed compare the least-significant byte of register _xs2_ to the loaded value, and select the maximum value + * Write the maximum to the address in _xs1_ +definedBy: Zabha +assembly: xd, xs2, (xs1) +encoding: + match: 1010010----------000-----0101111 + variables: + - name: xs2 + location: 24-20 + - name: xs1 + location: 19-15 + - name: xd + location: 11-7 +access: + s: always + u: always + vs: always + vu: always +operation(): | + if (!implemented?(ExtensionName::A) || (MISA_CSR_IMPLEMENTED && (CSR[misa].A == 1'b0))) { + raise (ExceptionCode::IllegalInstruction, mode(), $encoding); + } + + memory_model_acquire(); + + XReg virtual_address = X[xs1]; + X[xd] = amo<8>(virtual_address, X[xs2][7:0], AmoOperation::Max, 1'b1, 1'b0, $encoding); + +# SPDX-SnippetBegin +# SPDX-FileCopyrightText: 2017-2025 Contributors to the RISCV Sail Model +# SPDX-License-Identifier: BSD-2-Clause +sail(): | + { + if extension("A") then { + /* Get the address, X(rs1) (no offset). + * Some extensions perform additional checks on address validity. + */ + match ext_data_get_addr(rs1, zeros(), ReadWrite(Data, Data), width) { + Ext_DataAddr_Error(e) => { ext_handle_data_check_error(e); RETIRE_FAIL }, + Ext_DataAddr_OK(vaddr) => { + match translateAddr(vaddr, ReadWrite(Data, Data)) { + TR_Failure(e, _) => { handle_mem_exception(vaddr, e); RETIRE_FAIL }, + TR_Address(addr, _) => { + let eares : MemoryOpResult(unit) = match (width, sizeof(xlen)) { + (BYTE, _) => mem_write_ea(addr, 1, aq & rl, rl, true), + (HALF, _) => mem_write_ea(addr, 2, aq & rl, rl, true), + (WORD, _) => mem_write_ea(addr, 4, aq & rl, rl, true), + (DOUBLE, 64) => mem_write_ea(addr, 8, aq & rl, rl, true), + _ => internal_error(__FILE__, __LINE__, "Unexpected AMO width") + }; + let is_unsigned : bool = match op { + AMOMINU => true, + AMOMAXU => true, + _ => false + }; + let rs2_val : xlenbits = match width { + BYTE => if is_unsigned then zero_extend(X(rs2)[7..0]) else sign_extend(X(rs2)[7..0]), + HALF => if is_unsigned then zero_extend(X(rs2)[15..0]) else sign_extend(X(rs2)[15..0]), + WORD => if is_unsigned then zero_extend(X(rs2)[31..0]) else sign_extend(X(rs2)[31..0]), + DOUBLE => X(rs2) + }; + match (eares) { + MemException(e) => { handle_mem_exception(vaddr, e); RETIRE_FAIL }, + MemValue(_) => { + let mval : MemoryOpResult(xlenbits) = match (width, sizeof(xlen)) { + (BYTE, _) => extend_value(is_unsigned, mem_read(ReadWrite(Data, Data), addr, 1, aq, aq & rl, true)), + (HALF, _) => extend_value(is_unsigned, mem_read(ReadWrite(Data, Data), addr, 2, aq, aq & rl, true)), + (WORD, _) => extend_value(is_unsigned, mem_read(ReadWrite(Data, Data), addr, 4, aq, aq & rl, true)), + (DOUBLE, 64) => extend_value(is_unsigned, mem_read(ReadWrite(Data, Data), addr, 8, aq, aq & rl, true)), + _ => internal_error(__FILE__, __LINE__, "Unexpected AMO width") + }; + match (mval) { + MemException(e) => { handle_mem_exception(vaddr, e); RETIRE_FAIL }, + MemValue(loaded) => { + let result : xlenbits = + match op { + AMOSWAP => rs2_val, + AMOADD => rs2_val + loaded, + AMOXOR => rs2_val ^ loaded, + AMOAND => rs2_val & loaded, + AMOOR => rs2_val | loaded, + + /* These operations convert bitvectors to integer values using [un]signed, + * and back using to_bits(). + */ + AMOMIN => to_bits(sizeof(xlen), min(signed(rs2_val), signed(loaded))), + AMOMAX => to_bits(sizeof(xlen), max(signed(rs2_val), signed(loaded))), + AMOMINU => to_bits(sizeof(xlen), min(unsigned(rs2_val), unsigned(loaded))), + AMOMAXU => to_bits(sizeof(xlen), max(unsigned(rs2_val), unsigned(loaded))) + }; + let rval : xlenbits = match width { + BYTE => sign_extend(loaded[7..0]), + HALF => sign_extend(loaded[15..0]), + WORD => sign_extend(loaded[31..0]), + DOUBLE => loaded + }; + let wval : MemoryOpResult(bool) = match (width, sizeof(xlen)) { + (BYTE, _) => mem_write_value(addr, 1, result[7..0], aq & rl, rl, true), + (HALF, _) => mem_write_value(addr, 2, result[15..0], aq & rl, rl, true), + (WORD, _) => mem_write_value(addr, 4, result[31..0], aq & rl, rl, true), + (DOUBLE, 64) => mem_write_value(addr, 8, result, aq & rl, rl, true), + _ => internal_error(__FILE__, __LINE__, "Unexpected AMO width") + }; + match (wval) { + MemValue(true) => { X(rd) = rval; RETIRE_SUCCESS }, + MemValue(false) => { internal_error(__FILE__, __LINE__, "AMO got false from mem_write_value") }, + MemException(e) => { handle_mem_exception(vaddr, e); RETIRE_FAIL } + } + } + } + } + } + } + } + } + } + } else { + handle_illegal(); + RETIRE_FAIL + } + } + +# SPDX-SnippetEnd diff --git a/spec/std/isa/inst/Zabha/amomax.b.aqrl.yaml b/spec/std/isa/inst/Zabha/amomax.b.aqrl.yaml new file mode 100644 index 0000000000..a29092ddda --- /dev/null +++ b/spec/std/isa/inst/Zabha/amomax.b.aqrl.yaml @@ -0,0 +1,141 @@ +# Copyright (c) Qualcomm Technologies, Inc. and/or its subsidiaries. + +# WARNING: This file is auto-generated from spec/std/isa/inst/Zaamo/amomax.SIZE.AQRL.layout# Copyright (c) Abhijit Das(Sukuna0007Abhi) +# SPDX-License-Identifier: BSD-3-Clause-Clear + +# yaml-language-server: $schema=../../../../schemas/inst_schema.json + +$schema: "inst_schema.json#" +kind: instruction +name: amomax.b.aqrl +long_name: Atomic MAX byte (acquire-release) +description: | + Atomically with acquire and release ordering: + + * Load the byte at address _xs1_ + * Write the sign-extended value into _xd_ + * Signed compare the least-significant byte of register _xs2_ to the loaded value, and select the maximum value + * Write the maximum to the address in _xs1_ +definedBy: Zabha +assembly: xd, xs2, (xs1) +encoding: + match: 1010011----------000-----0101111 + variables: + - name: xs2 + location: 24-20 + - name: xs1 + location: 19-15 + - name: xd + location: 11-7 +access: + s: always + u: always + vs: always + vu: always +operation(): | + if (!implemented?(ExtensionName::A) || (MISA_CSR_IMPLEMENTED && (CSR[misa].A == 1'b0))) { + raise (ExceptionCode::IllegalInstruction, mode(), $encoding); + } + + memory_model_acquire(); + + XReg virtual_address = X[xs1]; + X[xd] = amo<8>(virtual_address, X[xs2][7:0], AmoOperation::Max, 1'b1, 1'b1, $encoding); + + memory_model_release(); + +# SPDX-SnippetBegin +# SPDX-FileCopyrightText: 2017-2025 Contributors to the RISCV Sail Model +# SPDX-License-Identifier: BSD-2-Clause +sail(): | + { + if extension("A") then { + /* Get the address, X(rs1) (no offset). + * Some extensions perform additional checks on address validity. + */ + match ext_data_get_addr(rs1, zeros(), ReadWrite(Data, Data), width) { + Ext_DataAddr_Error(e) => { ext_handle_data_check_error(e); RETIRE_FAIL }, + Ext_DataAddr_OK(vaddr) => { + match translateAddr(vaddr, ReadWrite(Data, Data)) { + TR_Failure(e, _) => { handle_mem_exception(vaddr, e); RETIRE_FAIL }, + TR_Address(addr, _) => { + let eares : MemoryOpResult(unit) = match (width, sizeof(xlen)) { + (BYTE, _) => mem_write_ea(addr, 1, aq & rl, rl, true), + (HALF, _) => mem_write_ea(addr, 2, aq & rl, rl, true), + (WORD, _) => mem_write_ea(addr, 4, aq & rl, rl, true), + (DOUBLE, 64) => mem_write_ea(addr, 8, aq & rl, rl, true), + _ => internal_error(__FILE__, __LINE__, "Unexpected AMO width") + }; + let is_unsigned : bool = match op { + AMOMINU => true, + AMOMAXU => true, + _ => false + }; + let rs2_val : xlenbits = match width { + BYTE => if is_unsigned then zero_extend(X(rs2)[7..0]) else sign_extend(X(rs2)[7..0]), + HALF => if is_unsigned then zero_extend(X(rs2)[15..0]) else sign_extend(X(rs2)[15..0]), + WORD => if is_unsigned then zero_extend(X(rs2)[31..0]) else sign_extend(X(rs2)[31..0]), + DOUBLE => X(rs2) + }; + match (eares) { + MemException(e) => { handle_mem_exception(vaddr, e); RETIRE_FAIL }, + MemValue(_) => { + let mval : MemoryOpResult(xlenbits) = match (width, sizeof(xlen)) { + (BYTE, _) => extend_value(is_unsigned, mem_read(ReadWrite(Data, Data), addr, 1, aq, aq & rl, true)), + (HALF, _) => extend_value(is_unsigned, mem_read(ReadWrite(Data, Data), addr, 2, aq, aq & rl, true)), + (WORD, _) => extend_value(is_unsigned, mem_read(ReadWrite(Data, Data), addr, 4, aq, aq & rl, true)), + (DOUBLE, 64) => extend_value(is_unsigned, mem_read(ReadWrite(Data, Data), addr, 8, aq, aq & rl, true)), + _ => internal_error(__FILE__, __LINE__, "Unexpected AMO width") + }; + match (mval) { + MemException(e) => { handle_mem_exception(vaddr, e); RETIRE_FAIL }, + MemValue(loaded) => { + let result : xlenbits = + match op { + AMOSWAP => rs2_val, + AMOADD => rs2_val + loaded, + AMOXOR => rs2_val ^ loaded, + AMOAND => rs2_val & loaded, + AMOOR => rs2_val | loaded, + + /* These operations convert bitvectors to integer values using [un]signed, + * and back using to_bits(). + */ + AMOMIN => to_bits(sizeof(xlen), min(signed(rs2_val), signed(loaded))), + AMOMAX => to_bits(sizeof(xlen), max(signed(rs2_val), signed(loaded))), + AMOMINU => to_bits(sizeof(xlen), min(unsigned(rs2_val), unsigned(loaded))), + AMOMAXU => to_bits(sizeof(xlen), max(unsigned(rs2_val), unsigned(loaded))) + }; + let rval : xlenbits = match width { + BYTE => sign_extend(loaded[7..0]), + HALF => sign_extend(loaded[15..0]), + WORD => sign_extend(loaded[31..0]), + DOUBLE => loaded + }; + let wval : MemoryOpResult(bool) = match (width, sizeof(xlen)) { + (BYTE, _) => mem_write_value(addr, 1, result[7..0], aq & rl, rl, true), + (HALF, _) => mem_write_value(addr, 2, result[15..0], aq & rl, rl, true), + (WORD, _) => mem_write_value(addr, 4, result[31..0], aq & rl, rl, true), + (DOUBLE, 64) => mem_write_value(addr, 8, result, aq & rl, rl, true), + _ => internal_error(__FILE__, __LINE__, "Unexpected AMO width") + }; + match (wval) { + MemValue(true) => { X(rd) = rval; RETIRE_SUCCESS }, + MemValue(false) => { internal_error(__FILE__, __LINE__, "AMO got false from mem_write_value") }, + MemException(e) => { handle_mem_exception(vaddr, e); RETIRE_FAIL } + } + } + } + } + } + } + } + } + } + } else { + handle_illegal(); + RETIRE_FAIL + } + } + +# SPDX-SnippetEnd diff --git a/spec/std/isa/inst/Zabha/amomax.b.rl.yaml b/spec/std/isa/inst/Zabha/amomax.b.rl.yaml new file mode 100644 index 0000000000..b24270fe9b --- /dev/null +++ b/spec/std/isa/inst/Zabha/amomax.b.rl.yaml @@ -0,0 +1,139 @@ +# Copyright (c) Qualcomm Technologies, Inc. and/or its subsidiaries. + +# WARNING: This file is auto-generated from spec/std/isa/inst/Zaamo/amomax.SIZE.AQRL.layout# Copyright (c) Abhijit Das(Sukuna0007Abhi) +# SPDX-License-Identifier: BSD-3-Clause-Clear + +# yaml-language-server: $schema=../../../../schemas/inst_schema.json + +$schema: "inst_schema.json#" +kind: instruction +name: amomax.b.rl +long_name: Atomic MAX byte (release) +description: | + Atomically with release ordering: + + * Load the byte at address _xs1_ + * Write the sign-extended value into _xd_ + * Signed compare the least-significant byte of register _xs2_ to the loaded value, and select the maximum value + * Write the maximum to the address in _xs1_ +definedBy: Zabha +assembly: xd, xs2, (xs1) +encoding: + match: 1010001----------000-----0101111 + variables: + - name: xs2 + location: 24-20 + - name: xs1 + location: 19-15 + - name: xd + location: 11-7 +access: + s: always + u: always + vs: always + vu: always +operation(): | + if (!implemented?(ExtensionName::A) || (MISA_CSR_IMPLEMENTED && (CSR[misa].A == 1'b0))) { + raise (ExceptionCode::IllegalInstruction, mode(), $encoding); + } + + XReg virtual_address = X[xs1]; + X[xd] = amo<8>(virtual_address, X[xs2][7:0], AmoOperation::Max, 1'b0, 1'b1, $encoding); + + memory_model_release(); + +# SPDX-SnippetBegin +# SPDX-FileCopyrightText: 2017-2025 Contributors to the RISCV Sail Model +# SPDX-License-Identifier: BSD-2-Clause +sail(): | + { + if extension("A") then { + /* Get the address, X(rs1) (no offset). + * Some extensions perform additional checks on address validity. + */ + match ext_data_get_addr(rs1, zeros(), ReadWrite(Data, Data), width) { + Ext_DataAddr_Error(e) => { ext_handle_data_check_error(e); RETIRE_FAIL }, + Ext_DataAddr_OK(vaddr) => { + match translateAddr(vaddr, ReadWrite(Data, Data)) { + TR_Failure(e, _) => { handle_mem_exception(vaddr, e); RETIRE_FAIL }, + TR_Address(addr, _) => { + let eares : MemoryOpResult(unit) = match (width, sizeof(xlen)) { + (BYTE, _) => mem_write_ea(addr, 1, aq & rl, rl, true), + (HALF, _) => mem_write_ea(addr, 2, aq & rl, rl, true), + (WORD, _) => mem_write_ea(addr, 4, aq & rl, rl, true), + (DOUBLE, 64) => mem_write_ea(addr, 8, aq & rl, rl, true), + _ => internal_error(__FILE__, __LINE__, "Unexpected AMO width") + }; + let is_unsigned : bool = match op { + AMOMINU => true, + AMOMAXU => true, + _ => false + }; + let rs2_val : xlenbits = match width { + BYTE => if is_unsigned then zero_extend(X(rs2)[7..0]) else sign_extend(X(rs2)[7..0]), + HALF => if is_unsigned then zero_extend(X(rs2)[15..0]) else sign_extend(X(rs2)[15..0]), + WORD => if is_unsigned then zero_extend(X(rs2)[31..0]) else sign_extend(X(rs2)[31..0]), + DOUBLE => X(rs2) + }; + match (eares) { + MemException(e) => { handle_mem_exception(vaddr, e); RETIRE_FAIL }, + MemValue(_) => { + let mval : MemoryOpResult(xlenbits) = match (width, sizeof(xlen)) { + (BYTE, _) => extend_value(is_unsigned, mem_read(ReadWrite(Data, Data), addr, 1, aq, aq & rl, true)), + (HALF, _) => extend_value(is_unsigned, mem_read(ReadWrite(Data, Data), addr, 2, aq, aq & rl, true)), + (WORD, _) => extend_value(is_unsigned, mem_read(ReadWrite(Data, Data), addr, 4, aq, aq & rl, true)), + (DOUBLE, 64) => extend_value(is_unsigned, mem_read(ReadWrite(Data, Data), addr, 8, aq, aq & rl, true)), + _ => internal_error(__FILE__, __LINE__, "Unexpected AMO width") + }; + match (mval) { + MemException(e) => { handle_mem_exception(vaddr, e); RETIRE_FAIL }, + MemValue(loaded) => { + let result : xlenbits = + match op { + AMOSWAP => rs2_val, + AMOADD => rs2_val + loaded, + AMOXOR => rs2_val ^ loaded, + AMOAND => rs2_val & loaded, + AMOOR => rs2_val | loaded, + + /* These operations convert bitvectors to integer values using [un]signed, + * and back using to_bits(). + */ + AMOMIN => to_bits(sizeof(xlen), min(signed(rs2_val), signed(loaded))), + AMOMAX => to_bits(sizeof(xlen), max(signed(rs2_val), signed(loaded))), + AMOMINU => to_bits(sizeof(xlen), min(unsigned(rs2_val), unsigned(loaded))), + AMOMAXU => to_bits(sizeof(xlen), max(unsigned(rs2_val), unsigned(loaded))) + }; + let rval : xlenbits = match width { + BYTE => sign_extend(loaded[7..0]), + HALF => sign_extend(loaded[15..0]), + WORD => sign_extend(loaded[31..0]), + DOUBLE => loaded + }; + let wval : MemoryOpResult(bool) = match (width, sizeof(xlen)) { + (BYTE, _) => mem_write_value(addr, 1, result[7..0], aq & rl, rl, true), + (HALF, _) => mem_write_value(addr, 2, result[15..0], aq & rl, rl, true), + (WORD, _) => mem_write_value(addr, 4, result[31..0], aq & rl, rl, true), + (DOUBLE, 64) => mem_write_value(addr, 8, result, aq & rl, rl, true), + _ => internal_error(__FILE__, __LINE__, "Unexpected AMO width") + }; + match (wval) { + MemValue(true) => { X(rd) = rval; RETIRE_SUCCESS }, + MemValue(false) => { internal_error(__FILE__, __LINE__, "AMO got false from mem_write_value") }, + MemException(e) => { handle_mem_exception(vaddr, e); RETIRE_FAIL } + } + } + } + } + } + } + } + } + } + } else { + handle_illegal(); + RETIRE_FAIL + } + } + +# SPDX-SnippetEnd diff --git a/spec/std/isa/inst/Zabha/amomax.b.yaml b/spec/std/isa/inst/Zabha/amomax.b.yaml index 7a2b01572f..fe3adfc748 100644 --- a/spec/std/isa/inst/Zabha/amomax.b.yaml +++ b/spec/std/isa/inst/Zabha/amomax.b.yaml @@ -1,4 +1,6 @@ # Copyright (c) Qualcomm Technologies, Inc. and/or its subsidiaries. + +# WARNING: This file is auto-generated from spec/std/isa/inst/Zaamo/amomax.SIZE.AQRL.layout# Copyright (c) Abhijit Das(Sukuna0007Abhi) # SPDX-License-Identifier: BSD-3-Clause-Clear # yaml-language-server: $schema=../../../../schemas/inst_schema.json @@ -6,18 +8,19 @@ $schema: "inst_schema.json#" kind: instruction name: amomax.b -long_name: No synopsis available +long_name: Atomic MAX byte description: | - No description available. + Atomically: + + * Load the byte at address _xs1_ + * Write the sign-extended value into _xd_ + * Signed compare the least-significant byte of register _xs2_ to the loaded value, and select the maximum value + * Write the maximum to the address in _xs1_ definedBy: Zabha assembly: xd, xs2, (xs1) encoding: - match: 10100------------000-----0101111 + match: 1010000----------000-----0101111 variables: - - name: aq - location: 26-26 - - name: rl - location: 25-25 - name: xs2 location: 24-20 - name: xs1 @@ -29,8 +32,13 @@ access: u: always vs: always vu: always -data_independent_timing: false operation(): | + if (!implemented?(ExtensionName::A) || (MISA_CSR_IMPLEMENTED && (CSR[misa].A == 1'b0))) { + raise (ExceptionCode::IllegalInstruction, mode(), $encoding); + } + + XReg virtual_address = X[xs1]; + X[xd] = amo<8>(virtual_address, X[xs2][7:0], AmoOperation::Max, 1'b0, 1'b0, $encoding); # SPDX-SnippetBegin # SPDX-FileCopyrightText: 2017-2025 Contributors to the RISCV Sail Model diff --git a/spec/std/isa/inst/Zabha/amomax.h.aq.yaml b/spec/std/isa/inst/Zabha/amomax.h.aq.yaml new file mode 100644 index 0000000000..4179f43a75 --- /dev/null +++ b/spec/std/isa/inst/Zabha/amomax.h.aq.yaml @@ -0,0 +1,139 @@ +# Copyright (c) Qualcomm Technologies, Inc. and/or its subsidiaries. + +# WARNING: This file is auto-generated from spec/std/isa/inst/Zaamo/amomax.SIZE.AQRL.layout# Copyright (c) Abhijit Das(Sukuna0007Abhi) +# SPDX-License-Identifier: BSD-3-Clause-Clear + +# yaml-language-server: $schema=../../../../schemas/inst_schema.json + +$schema: "inst_schema.json#" +kind: instruction +name: amomax.h.aq +long_name: Atomic MAX halfword (acquire) +description: | + Atomically with acquire ordering: + + * Load the halfword at address _xs1_ + * Write the sign-extended value into _xd_ + * Signed compare the least-significant halfword of register _xs2_ to the loaded value, and select the maximum value + * Write the maximum to the address in _xs1_ +definedBy: Zabha +assembly: xd, xs2, (xs1) +encoding: + match: 1010010----------001-----0101111 + variables: + - name: xs2 + location: 24-20 + - name: xs1 + location: 19-15 + - name: xd + location: 11-7 +access: + s: always + u: always + vs: always + vu: always +operation(): | + if (!implemented?(ExtensionName::A) || (MISA_CSR_IMPLEMENTED && (CSR[misa].A == 1'b0))) { + raise (ExceptionCode::IllegalInstruction, mode(), $encoding); + } + + memory_model_acquire(); + + XReg virtual_address = X[xs1]; + X[xd] = amo<16>(virtual_address, X[xs2][15:0], AmoOperation::Max, 1'b1, 1'b0, $encoding); + +# SPDX-SnippetBegin +# SPDX-FileCopyrightText: 2017-2025 Contributors to the RISCV Sail Model +# SPDX-License-Identifier: BSD-2-Clause +sail(): | + { + if extension("A") then { + /* Get the address, X(rs1) (no offset). + * Some extensions perform additional checks on address validity. + */ + match ext_data_get_addr(rs1, zeros(), ReadWrite(Data, Data), width) { + Ext_DataAddr_Error(e) => { ext_handle_data_check_error(e); RETIRE_FAIL }, + Ext_DataAddr_OK(vaddr) => { + match translateAddr(vaddr, ReadWrite(Data, Data)) { + TR_Failure(e, _) => { handle_mem_exception(vaddr, e); RETIRE_FAIL }, + TR_Address(addr, _) => { + let eares : MemoryOpResult(unit) = match (width, sizeof(xlen)) { + (BYTE, _) => mem_write_ea(addr, 1, aq & rl, rl, true), + (HALF, _) => mem_write_ea(addr, 2, aq & rl, rl, true), + (WORD, _) => mem_write_ea(addr, 4, aq & rl, rl, true), + (DOUBLE, 64) => mem_write_ea(addr, 8, aq & rl, rl, true), + _ => internal_error(__FILE__, __LINE__, "Unexpected AMO width") + }; + let is_unsigned : bool = match op { + AMOMINU => true, + AMOMAXU => true, + _ => false + }; + let rs2_val : xlenbits = match width { + BYTE => if is_unsigned then zero_extend(X(rs2)[7..0]) else sign_extend(X(rs2)[7..0]), + HALF => if is_unsigned then zero_extend(X(rs2)[15..0]) else sign_extend(X(rs2)[15..0]), + WORD => if is_unsigned then zero_extend(X(rs2)[31..0]) else sign_extend(X(rs2)[31..0]), + DOUBLE => X(rs2) + }; + match (eares) { + MemException(e) => { handle_mem_exception(vaddr, e); RETIRE_FAIL }, + MemValue(_) => { + let mval : MemoryOpResult(xlenbits) = match (width, sizeof(xlen)) { + (BYTE, _) => extend_value(is_unsigned, mem_read(ReadWrite(Data, Data), addr, 1, aq, aq & rl, true)), + (HALF, _) => extend_value(is_unsigned, mem_read(ReadWrite(Data, Data), addr, 2, aq, aq & rl, true)), + (WORD, _) => extend_value(is_unsigned, mem_read(ReadWrite(Data, Data), addr, 4, aq, aq & rl, true)), + (DOUBLE, 64) => extend_value(is_unsigned, mem_read(ReadWrite(Data, Data), addr, 8, aq, aq & rl, true)), + _ => internal_error(__FILE__, __LINE__, "Unexpected AMO width") + }; + match (mval) { + MemException(e) => { handle_mem_exception(vaddr, e); RETIRE_FAIL }, + MemValue(loaded) => { + let result : xlenbits = + match op { + AMOSWAP => rs2_val, + AMOADD => rs2_val + loaded, + AMOXOR => rs2_val ^ loaded, + AMOAND => rs2_val & loaded, + AMOOR => rs2_val | loaded, + + /* These operations convert bitvectors to integer values using [un]signed, + * and back using to_bits(). + */ + AMOMIN => to_bits(sizeof(xlen), min(signed(rs2_val), signed(loaded))), + AMOMAX => to_bits(sizeof(xlen), max(signed(rs2_val), signed(loaded))), + AMOMINU => to_bits(sizeof(xlen), min(unsigned(rs2_val), unsigned(loaded))), + AMOMAXU => to_bits(sizeof(xlen), max(unsigned(rs2_val), unsigned(loaded))) + }; + let rval : xlenbits = match width { + BYTE => sign_extend(loaded[7..0]), + HALF => sign_extend(loaded[15..0]), + WORD => sign_extend(loaded[31..0]), + DOUBLE => loaded + }; + let wval : MemoryOpResult(bool) = match (width, sizeof(xlen)) { + (BYTE, _) => mem_write_value(addr, 1, result[7..0], aq & rl, rl, true), + (HALF, _) => mem_write_value(addr, 2, result[15..0], aq & rl, rl, true), + (WORD, _) => mem_write_value(addr, 4, result[31..0], aq & rl, rl, true), + (DOUBLE, 64) => mem_write_value(addr, 8, result, aq & rl, rl, true), + _ => internal_error(__FILE__, __LINE__, "Unexpected AMO width") + }; + match (wval) { + MemValue(true) => { X(rd) = rval; RETIRE_SUCCESS }, + MemValue(false) => { internal_error(__FILE__, __LINE__, "AMO got false from mem_write_value") }, + MemException(e) => { handle_mem_exception(vaddr, e); RETIRE_FAIL } + } + } + } + } + } + } + } + } + } + } else { + handle_illegal(); + RETIRE_FAIL + } + } + +# SPDX-SnippetEnd diff --git a/spec/std/isa/inst/Zabha/amomax.h.aqrl.yaml b/spec/std/isa/inst/Zabha/amomax.h.aqrl.yaml new file mode 100644 index 0000000000..6971ce1c03 --- /dev/null +++ b/spec/std/isa/inst/Zabha/amomax.h.aqrl.yaml @@ -0,0 +1,141 @@ +# Copyright (c) Qualcomm Technologies, Inc. and/or its subsidiaries. + +# WARNING: This file is auto-generated from spec/std/isa/inst/Zaamo/amomax.SIZE.AQRL.layout# Copyright (c) Abhijit Das(Sukuna0007Abhi) +# SPDX-License-Identifier: BSD-3-Clause-Clear + +# yaml-language-server: $schema=../../../../schemas/inst_schema.json + +$schema: "inst_schema.json#" +kind: instruction +name: amomax.h.aqrl +long_name: Atomic MAX halfword (acquire-release) +description: | + Atomically with acquire and release ordering: + + * Load the halfword at address _xs1_ + * Write the sign-extended value into _xd_ + * Signed compare the least-significant halfword of register _xs2_ to the loaded value, and select the maximum value + * Write the maximum to the address in _xs1_ +definedBy: Zabha +assembly: xd, xs2, (xs1) +encoding: + match: 1010011----------001-----0101111 + variables: + - name: xs2 + location: 24-20 + - name: xs1 + location: 19-15 + - name: xd + location: 11-7 +access: + s: always + u: always + vs: always + vu: always +operation(): | + if (!implemented?(ExtensionName::A) || (MISA_CSR_IMPLEMENTED && (CSR[misa].A == 1'b0))) { + raise (ExceptionCode::IllegalInstruction, mode(), $encoding); + } + + memory_model_acquire(); + + XReg virtual_address = X[xs1]; + X[xd] = amo<16>(virtual_address, X[xs2][15:0], AmoOperation::Max, 1'b1, 1'b1, $encoding); + + memory_model_release(); + +# SPDX-SnippetBegin +# SPDX-FileCopyrightText: 2017-2025 Contributors to the RISCV Sail Model +# SPDX-License-Identifier: BSD-2-Clause +sail(): | + { + if extension("A") then { + /* Get the address, X(rs1) (no offset). + * Some extensions perform additional checks on address validity. + */ + match ext_data_get_addr(rs1, zeros(), ReadWrite(Data, Data), width) { + Ext_DataAddr_Error(e) => { ext_handle_data_check_error(e); RETIRE_FAIL }, + Ext_DataAddr_OK(vaddr) => { + match translateAddr(vaddr, ReadWrite(Data, Data)) { + TR_Failure(e, _) => { handle_mem_exception(vaddr, e); RETIRE_FAIL }, + TR_Address(addr, _) => { + let eares : MemoryOpResult(unit) = match (width, sizeof(xlen)) { + (BYTE, _) => mem_write_ea(addr, 1, aq & rl, rl, true), + (HALF, _) => mem_write_ea(addr, 2, aq & rl, rl, true), + (WORD, _) => mem_write_ea(addr, 4, aq & rl, rl, true), + (DOUBLE, 64) => mem_write_ea(addr, 8, aq & rl, rl, true), + _ => internal_error(__FILE__, __LINE__, "Unexpected AMO width") + }; + let is_unsigned : bool = match op { + AMOMINU => true, + AMOMAXU => true, + _ => false + }; + let rs2_val : xlenbits = match width { + BYTE => if is_unsigned then zero_extend(X(rs2)[7..0]) else sign_extend(X(rs2)[7..0]), + HALF => if is_unsigned then zero_extend(X(rs2)[15..0]) else sign_extend(X(rs2)[15..0]), + WORD => if is_unsigned then zero_extend(X(rs2)[31..0]) else sign_extend(X(rs2)[31..0]), + DOUBLE => X(rs2) + }; + match (eares) { + MemException(e) => { handle_mem_exception(vaddr, e); RETIRE_FAIL }, + MemValue(_) => { + let mval : MemoryOpResult(xlenbits) = match (width, sizeof(xlen)) { + (BYTE, _) => extend_value(is_unsigned, mem_read(ReadWrite(Data, Data), addr, 1, aq, aq & rl, true)), + (HALF, _) => extend_value(is_unsigned, mem_read(ReadWrite(Data, Data), addr, 2, aq, aq & rl, true)), + (WORD, _) => extend_value(is_unsigned, mem_read(ReadWrite(Data, Data), addr, 4, aq, aq & rl, true)), + (DOUBLE, 64) => extend_value(is_unsigned, mem_read(ReadWrite(Data, Data), addr, 8, aq, aq & rl, true)), + _ => internal_error(__FILE__, __LINE__, "Unexpected AMO width") + }; + match (mval) { + MemException(e) => { handle_mem_exception(vaddr, e); RETIRE_FAIL }, + MemValue(loaded) => { + let result : xlenbits = + match op { + AMOSWAP => rs2_val, + AMOADD => rs2_val + loaded, + AMOXOR => rs2_val ^ loaded, + AMOAND => rs2_val & loaded, + AMOOR => rs2_val | loaded, + + /* These operations convert bitvectors to integer values using [un]signed, + * and back using to_bits(). + */ + AMOMIN => to_bits(sizeof(xlen), min(signed(rs2_val), signed(loaded))), + AMOMAX => to_bits(sizeof(xlen), max(signed(rs2_val), signed(loaded))), + AMOMINU => to_bits(sizeof(xlen), min(unsigned(rs2_val), unsigned(loaded))), + AMOMAXU => to_bits(sizeof(xlen), max(unsigned(rs2_val), unsigned(loaded))) + }; + let rval : xlenbits = match width { + BYTE => sign_extend(loaded[7..0]), + HALF => sign_extend(loaded[15..0]), + WORD => sign_extend(loaded[31..0]), + DOUBLE => loaded + }; + let wval : MemoryOpResult(bool) = match (width, sizeof(xlen)) { + (BYTE, _) => mem_write_value(addr, 1, result[7..0], aq & rl, rl, true), + (HALF, _) => mem_write_value(addr, 2, result[15..0], aq & rl, rl, true), + (WORD, _) => mem_write_value(addr, 4, result[31..0], aq & rl, rl, true), + (DOUBLE, 64) => mem_write_value(addr, 8, result, aq & rl, rl, true), + _ => internal_error(__FILE__, __LINE__, "Unexpected AMO width") + }; + match (wval) { + MemValue(true) => { X(rd) = rval; RETIRE_SUCCESS }, + MemValue(false) => { internal_error(__FILE__, __LINE__, "AMO got false from mem_write_value") }, + MemException(e) => { handle_mem_exception(vaddr, e); RETIRE_FAIL } + } + } + } + } + } + } + } + } + } + } else { + handle_illegal(); + RETIRE_FAIL + } + } + +# SPDX-SnippetEnd diff --git a/spec/std/isa/inst/Zabha/amomax.h.rl.yaml b/spec/std/isa/inst/Zabha/amomax.h.rl.yaml new file mode 100644 index 0000000000..1de65afb60 --- /dev/null +++ b/spec/std/isa/inst/Zabha/amomax.h.rl.yaml @@ -0,0 +1,139 @@ +# Copyright (c) Qualcomm Technologies, Inc. and/or its subsidiaries. + +# WARNING: This file is auto-generated from spec/std/isa/inst/Zaamo/amomax.SIZE.AQRL.layout# Copyright (c) Abhijit Das(Sukuna0007Abhi) +# SPDX-License-Identifier: BSD-3-Clause-Clear + +# yaml-language-server: $schema=../../../../schemas/inst_schema.json + +$schema: "inst_schema.json#" +kind: instruction +name: amomax.h.rl +long_name: Atomic MAX halfword (release) +description: | + Atomically with release ordering: + + * Load the halfword at address _xs1_ + * Write the sign-extended value into _xd_ + * Signed compare the least-significant halfword of register _xs2_ to the loaded value, and select the maximum value + * Write the maximum to the address in _xs1_ +definedBy: Zabha +assembly: xd, xs2, (xs1) +encoding: + match: 1010001----------001-----0101111 + variables: + - name: xs2 + location: 24-20 + - name: xs1 + location: 19-15 + - name: xd + location: 11-7 +access: + s: always + u: always + vs: always + vu: always +operation(): | + if (!implemented?(ExtensionName::A) || (MISA_CSR_IMPLEMENTED && (CSR[misa].A == 1'b0))) { + raise (ExceptionCode::IllegalInstruction, mode(), $encoding); + } + + XReg virtual_address = X[xs1]; + X[xd] = amo<16>(virtual_address, X[xs2][15:0], AmoOperation::Max, 1'b0, 1'b1, $encoding); + + memory_model_release(); + +# SPDX-SnippetBegin +# SPDX-FileCopyrightText: 2017-2025 Contributors to the RISCV Sail Model +# SPDX-License-Identifier: BSD-2-Clause +sail(): | + { + if extension("A") then { + /* Get the address, X(rs1) (no offset). + * Some extensions perform additional checks on address validity. + */ + match ext_data_get_addr(rs1, zeros(), ReadWrite(Data, Data), width) { + Ext_DataAddr_Error(e) => { ext_handle_data_check_error(e); RETIRE_FAIL }, + Ext_DataAddr_OK(vaddr) => { + match translateAddr(vaddr, ReadWrite(Data, Data)) { + TR_Failure(e, _) => { handle_mem_exception(vaddr, e); RETIRE_FAIL }, + TR_Address(addr, _) => { + let eares : MemoryOpResult(unit) = match (width, sizeof(xlen)) { + (BYTE, _) => mem_write_ea(addr, 1, aq & rl, rl, true), + (HALF, _) => mem_write_ea(addr, 2, aq & rl, rl, true), + (WORD, _) => mem_write_ea(addr, 4, aq & rl, rl, true), + (DOUBLE, 64) => mem_write_ea(addr, 8, aq & rl, rl, true), + _ => internal_error(__FILE__, __LINE__, "Unexpected AMO width") + }; + let is_unsigned : bool = match op { + AMOMINU => true, + AMOMAXU => true, + _ => false + }; + let rs2_val : xlenbits = match width { + BYTE => if is_unsigned then zero_extend(X(rs2)[7..0]) else sign_extend(X(rs2)[7..0]), + HALF => if is_unsigned then zero_extend(X(rs2)[15..0]) else sign_extend(X(rs2)[15..0]), + WORD => if is_unsigned then zero_extend(X(rs2)[31..0]) else sign_extend(X(rs2)[31..0]), + DOUBLE => X(rs2) + }; + match (eares) { + MemException(e) => { handle_mem_exception(vaddr, e); RETIRE_FAIL }, + MemValue(_) => { + let mval : MemoryOpResult(xlenbits) = match (width, sizeof(xlen)) { + (BYTE, _) => extend_value(is_unsigned, mem_read(ReadWrite(Data, Data), addr, 1, aq, aq & rl, true)), + (HALF, _) => extend_value(is_unsigned, mem_read(ReadWrite(Data, Data), addr, 2, aq, aq & rl, true)), + (WORD, _) => extend_value(is_unsigned, mem_read(ReadWrite(Data, Data), addr, 4, aq, aq & rl, true)), + (DOUBLE, 64) => extend_value(is_unsigned, mem_read(ReadWrite(Data, Data), addr, 8, aq, aq & rl, true)), + _ => internal_error(__FILE__, __LINE__, "Unexpected AMO width") + }; + match (mval) { + MemException(e) => { handle_mem_exception(vaddr, e); RETIRE_FAIL }, + MemValue(loaded) => { + let result : xlenbits = + match op { + AMOSWAP => rs2_val, + AMOADD => rs2_val + loaded, + AMOXOR => rs2_val ^ loaded, + AMOAND => rs2_val & loaded, + AMOOR => rs2_val | loaded, + + /* These operations convert bitvectors to integer values using [un]signed, + * and back using to_bits(). + */ + AMOMIN => to_bits(sizeof(xlen), min(signed(rs2_val), signed(loaded))), + AMOMAX => to_bits(sizeof(xlen), max(signed(rs2_val), signed(loaded))), + AMOMINU => to_bits(sizeof(xlen), min(unsigned(rs2_val), unsigned(loaded))), + AMOMAXU => to_bits(sizeof(xlen), max(unsigned(rs2_val), unsigned(loaded))) + }; + let rval : xlenbits = match width { + BYTE => sign_extend(loaded[7..0]), + HALF => sign_extend(loaded[15..0]), + WORD => sign_extend(loaded[31..0]), + DOUBLE => loaded + }; + let wval : MemoryOpResult(bool) = match (width, sizeof(xlen)) { + (BYTE, _) => mem_write_value(addr, 1, result[7..0], aq & rl, rl, true), + (HALF, _) => mem_write_value(addr, 2, result[15..0], aq & rl, rl, true), + (WORD, _) => mem_write_value(addr, 4, result[31..0], aq & rl, rl, true), + (DOUBLE, 64) => mem_write_value(addr, 8, result, aq & rl, rl, true), + _ => internal_error(__FILE__, __LINE__, "Unexpected AMO width") + }; + match (wval) { + MemValue(true) => { X(rd) = rval; RETIRE_SUCCESS }, + MemValue(false) => { internal_error(__FILE__, __LINE__, "AMO got false from mem_write_value") }, + MemException(e) => { handle_mem_exception(vaddr, e); RETIRE_FAIL } + } + } + } + } + } + } + } + } + } + } else { + handle_illegal(); + RETIRE_FAIL + } + } + +# SPDX-SnippetEnd diff --git a/spec/std/isa/inst/Zabha/amomax.h.yaml b/spec/std/isa/inst/Zabha/amomax.h.yaml index 55ad22cc7e..d23a3f1445 100644 --- a/spec/std/isa/inst/Zabha/amomax.h.yaml +++ b/spec/std/isa/inst/Zabha/amomax.h.yaml @@ -1,4 +1,6 @@ # Copyright (c) Qualcomm Technologies, Inc. and/or its subsidiaries. + +# WARNING: This file is auto-generated from spec/std/isa/inst/Zaamo/amomax.SIZE.AQRL.layout# Copyright (c) Abhijit Das(Sukuna0007Abhi) # SPDX-License-Identifier: BSD-3-Clause-Clear # yaml-language-server: $schema=../../../../schemas/inst_schema.json @@ -6,18 +8,19 @@ $schema: "inst_schema.json#" kind: instruction name: amomax.h -long_name: No synopsis available +long_name: Atomic MAX halfword description: | - No description available. + Atomically: + + * Load the halfword at address _xs1_ + * Write the sign-extended value into _xd_ + * Signed compare the least-significant halfword of register _xs2_ to the loaded value, and select the maximum value + * Write the maximum to the address in _xs1_ definedBy: Zabha assembly: xd, xs2, (xs1) encoding: - match: 10100------------001-----0101111 + match: 1010000----------001-----0101111 variables: - - name: aq - location: 26-26 - - name: rl - location: 25-25 - name: xs2 location: 24-20 - name: xs1 @@ -29,8 +32,13 @@ access: u: always vs: always vu: always -data_independent_timing: false operation(): | + if (!implemented?(ExtensionName::A) || (MISA_CSR_IMPLEMENTED && (CSR[misa].A == 1'b0))) { + raise (ExceptionCode::IllegalInstruction, mode(), $encoding); + } + + XReg virtual_address = X[xs1]; + X[xd] = amo<16>(virtual_address, X[xs2][15:0], AmoOperation::Max, 1'b0, 1'b0, $encoding); # SPDX-SnippetBegin # SPDX-FileCopyrightText: 2017-2025 Contributors to the RISCV Sail Model diff --git a/spec/std/isa/inst/Zabha/amomaxu.b.aq.yaml b/spec/std/isa/inst/Zabha/amomaxu.b.aq.yaml new file mode 100644 index 0000000000..4ef04327c0 --- /dev/null +++ b/spec/std/isa/inst/Zabha/amomaxu.b.aq.yaml @@ -0,0 +1,139 @@ +# Copyright (c) Qualcomm Technologies, Inc. and/or its subsidiaries. + +# WARNING: This file is auto-generated from spec/std/isa/inst/Zaamo/amomaxu.SIZE.AQRL.layout# Copyright (c) Abhijit Das(Sukuna0007Abhi) +# SPDX-License-Identifier: BSD-3-Clause-Clear + +# yaml-language-server: $schema=../../../../schemas/inst_schema.json + +$schema: "inst_schema.json#" +kind: instruction +name: amomaxu.b.aq +long_name: Atomic MAX unsigned byte (acquire) +description: | + Atomically with acquire ordering: + + * Load the byte at address _xs1_ + * Write the sign-extended value into _xd_ + * Unsigned compare the least-significant byte of register _xs2_ to the loaded value, and select the maximum value + * Write the maximum to the address in _xs1_ +definedBy: Zabha +assembly: xd, xs2, (xs1) +encoding: + match: 1110010----------000-----0101111 + variables: + - name: xs2 + location: 24-20 + - name: xs1 + location: 19-15 + - name: xd + location: 11-7 +access: + s: always + u: always + vs: always + vu: always +operation(): | + if (!implemented?(ExtensionName::A) || (MISA_CSR_IMPLEMENTED && (CSR[misa].A == 1'b0))) { + raise (ExceptionCode::IllegalInstruction, mode(), $encoding); + } + + memory_model_acquire(); + + XReg virtual_address = X[xs1]; + X[xd] = amo<8>(virtual_address, X[xs2][7:0], AmoOperation::Maxu, 1'b1, 1'b0, $encoding); + +# SPDX-SnippetBegin +# SPDX-FileCopyrightText: 2017-2025 Contributors to the RISCV Sail Model +# SPDX-License-Identifier: BSD-2-Clause +sail(): | + { + if extension("A") then { + /* Get the address, X(rs1) (no offset). + * Some extensions perform additional checks on address validity. + */ + match ext_data_get_addr(rs1, zeros(), ReadWrite(Data, Data), width) { + Ext_DataAddr_Error(e) => { ext_handle_data_check_error(e); RETIRE_FAIL }, + Ext_DataAddr_OK(vaddr) => { + match translateAddr(vaddr, ReadWrite(Data, Data)) { + TR_Failure(e, _) => { handle_mem_exception(vaddr, e); RETIRE_FAIL }, + TR_Address(addr, _) => { + let eares : MemoryOpResult(unit) = match (width, sizeof(xlen)) { + (BYTE, _) => mem_write_ea(addr, 1, true & false, false, true), + (HALF, _) => mem_write_ea(addr, 2, true & false, false, true), + (WORD, _) => mem_write_ea(addr, 4, true & false, false, true), + (DOUBLE, 64) => mem_write_ea(addr, 8, true & false, false, true), + _ => internal_error(__FILE__, __LINE__, "Unexpected AMO width") + }; + let is_unsigned : bool = match op { + AMOMINU => true, + AMOMAXU => true, + _ => false + }; + let xs2_val : xlenbits = match width { + BYTE => if is_unsigned then zero_extend(X(rs2)[7..0]) else sign_extend(X(rs2)[7..0]), + HALF => if is_unsigned then zero_extend(X(rs2)[15..0]) else sign_extend(X(rs2)[15..0]), + WORD => if is_unsigned then zero_extend(X(rs2)[31..0]) else sign_extend(X(rs2)[31..0]), + DOUBLE => X(rs2) + }; + match (eares) { + MemException(e) => { handle_mem_exception(vaddr, e); RETIRE_FAIL }, + MemValue(_) => { + let mval : MemoryOpResult(xlenbits) = match (width, sizeof(xlen)) { + (BYTE, _) => extend_value(is_unsigned, mem_read(ReadWrite(Data, Data), addr, 1, true, true & false, true)), + (HALF, _) => extend_value(is_unsigned, mem_read(ReadWrite(Data, Data), addr, 2, true, true & false, true)), + (WORD, _) => extend_value(is_unsigned, mem_read(ReadWrite(Data, Data), addr, 4, true, true & false, true)), + (DOUBLE, 64) => extend_value(is_unsigned, mem_read(ReadWrite(Data, Data), addr, 8, true, true & false, true)), + _ => internal_error(__FILE__, __LINE__, "Unexpected AMO width") + }; + match (mval) { + MemException(e) => { handle_mem_exception(vaddr, e); RETIRE_FAIL }, + MemValue(loaded) => { + let result : xlenbits = + match op { + AMOSWAP => xs2_val, + AMOADD => xs2_val + loaded, + AMOXOR => xs2_val ^ loaded, + AMOAND => xs2_val & loaded, + AMOOR => xs2_val | loaded, + + /* These operations convert bitvectors to integer values using [un]signed, + * and back using to_bits(). + */ + AMOMIN => to_bits(sizeof(xlen), min(signed(xs2_val), signed(loaded))), + AMOMAX => to_bits(sizeof(xlen), max(signed(xs2_val), signed(loaded))), + AMOMINU => to_bits(sizeof(xlen), min(unsigned(xs2_val), unsigned(loaded))), + AMOMAXU => to_bits(sizeof(xlen), max(unsigned(xs2_val), unsigned(loaded))) + }; + let rval : xlenbits = match width { + BYTE => sign_extend(loaded[7..0]), + HALF => sign_extend(loaded[15..0]), + WORD => sign_extend(loaded[31..0]), + DOUBLE => loaded + }; + let wval : MemoryOpResult(bool) = match (width, sizeof(xlen)) { + (BYTE, _) => mem_write_value(addr, 1, result[7..0], true & false, false, true), + (HALF, _) => mem_write_value(addr, 2, result[15..0], true & false, false, true), + (WORD, _) => mem_write_value(addr, 4, result[31..0], true & false, false, true), + (DOUBLE, 64) => mem_write_value(addr, 8, result, true & false, false, true), + _ => internal_error(__FILE__, __LINE__, "Unexpected AMO width") + }; + match (wval) { + MemValue(true) => { X(rd) = rval; RETIRE_SUCCESS }, + MemValue(false) => { internal_error(__FILE__, __LINE__, "AMO got false from mem_write_value") }, + MemException(e) => { handle_mem_exception(vaddr, e); RETIRE_FAIL } + } + } + } + } + } + } + } + } + } + } else { + handle_illegal(); + RETIRE_FAIL + } + } + +# SPDX-SnippetEnd diff --git a/spec/std/isa/inst/Zabha/amomaxu.b.aqrl.yaml b/spec/std/isa/inst/Zabha/amomaxu.b.aqrl.yaml new file mode 100644 index 0000000000..7cf5e09522 --- /dev/null +++ b/spec/std/isa/inst/Zabha/amomaxu.b.aqrl.yaml @@ -0,0 +1,141 @@ +# Copyright (c) Qualcomm Technologies, Inc. and/or its subsidiaries. + +# WARNING: This file is auto-generated from spec/std/isa/inst/Zaamo/amomaxu.SIZE.AQRL.layout# Copyright (c) Abhijit Das(Sukuna0007Abhi) +# SPDX-License-Identifier: BSD-3-Clause-Clear + +# yaml-language-server: $schema=../../../../schemas/inst_schema.json + +$schema: "inst_schema.json#" +kind: instruction +name: amomaxu.b.aqrl +long_name: Atomic MAX unsigned byte (acquire-release) +description: | + Atomically with acquire and release ordering: + + * Load the byte at address _xs1_ + * Write the sign-extended value into _xd_ + * Unsigned compare the least-significant byte of register _xs2_ to the loaded value, and select the maximum value + * Write the maximum to the address in _xs1_ +definedBy: Zabha +assembly: xd, xs2, (xs1) +encoding: + match: 1110011----------000-----0101111 + variables: + - name: xs2 + location: 24-20 + - name: xs1 + location: 19-15 + - name: xd + location: 11-7 +access: + s: always + u: always + vs: always + vu: always +operation(): | + if (!implemented?(ExtensionName::A) || (MISA_CSR_IMPLEMENTED && (CSR[misa].A == 1'b0))) { + raise (ExceptionCode::IllegalInstruction, mode(), $encoding); + } + + memory_model_acquire(); + + XReg virtual_address = X[xs1]; + X[xd] = amo<8>(virtual_address, X[xs2][7:0], AmoOperation::Maxu, 1'b1, 1'b1, $encoding); + + memory_model_release(); + +# SPDX-SnippetBegin +# SPDX-FileCopyrightText: 2017-2025 Contributors to the RISCV Sail Model +# SPDX-License-Identifier: BSD-2-Clause +sail(): | + { + if extension("A") then { + /* Get the address, X(rs1) (no offset). + * Some extensions perform additional checks on address validity. + */ + match ext_data_get_addr(rs1, zeros(), ReadWrite(Data, Data), width) { + Ext_DataAddr_Error(e) => { ext_handle_data_check_error(e); RETIRE_FAIL }, + Ext_DataAddr_OK(vaddr) => { + match translateAddr(vaddr, ReadWrite(Data, Data)) { + TR_Failure(e, _) => { handle_mem_exception(vaddr, e); RETIRE_FAIL }, + TR_Address(addr, _) => { + let eares : MemoryOpResult(unit) = match (width, sizeof(xlen)) { + (BYTE, _) => mem_write_ea(addr, 1, true & true, true, true), + (HALF, _) => mem_write_ea(addr, 2, true & true, true, true), + (WORD, _) => mem_write_ea(addr, 4, true & true, true, true), + (DOUBLE, 64) => mem_write_ea(addr, 8, true & true, true, true), + _ => internal_error(__FILE__, __LINE__, "Unexpected AMO width") + }; + let is_unsigned : bool = match op { + AMOMINU => true, + AMOMAXU => true, + _ => false + }; + let xs2_val : xlenbits = match width { + BYTE => if is_unsigned then zero_extend(X(rs2)[7..0]) else sign_extend(X(rs2)[7..0]), + HALF => if is_unsigned then zero_extend(X(rs2)[15..0]) else sign_extend(X(rs2)[15..0]), + WORD => if is_unsigned then zero_extend(X(rs2)[31..0]) else sign_extend(X(rs2)[31..0]), + DOUBLE => X(rs2) + }; + match (eares) { + MemException(e) => { handle_mem_exception(vaddr, e); RETIRE_FAIL }, + MemValue(_) => { + let mval : MemoryOpResult(xlenbits) = match (width, sizeof(xlen)) { + (BYTE, _) => extend_value(is_unsigned, mem_read(ReadWrite(Data, Data), addr, 1, true, true & true, true)), + (HALF, _) => extend_value(is_unsigned, mem_read(ReadWrite(Data, Data), addr, 2, true, true & true, true)), + (WORD, _) => extend_value(is_unsigned, mem_read(ReadWrite(Data, Data), addr, 4, true, true & true, true)), + (DOUBLE, 64) => extend_value(is_unsigned, mem_read(ReadWrite(Data, Data), addr, 8, true, true & true, true)), + _ => internal_error(__FILE__, __LINE__, "Unexpected AMO width") + }; + match (mval) { + MemException(e) => { handle_mem_exception(vaddr, e); RETIRE_FAIL }, + MemValue(loaded) => { + let result : xlenbits = + match op { + AMOSWAP => xs2_val, + AMOADD => xs2_val + loaded, + AMOXOR => xs2_val ^ loaded, + AMOAND => xs2_val & loaded, + AMOOR => xs2_val | loaded, + + /* These operations convert bitvectors to integer values using [un]signed, + * and back using to_bits(). + */ + AMOMIN => to_bits(sizeof(xlen), min(signed(xs2_val), signed(loaded))), + AMOMAX => to_bits(sizeof(xlen), max(signed(xs2_val), signed(loaded))), + AMOMINU => to_bits(sizeof(xlen), min(unsigned(xs2_val), unsigned(loaded))), + AMOMAXU => to_bits(sizeof(xlen), max(unsigned(xs2_val), unsigned(loaded))) + }; + let rval : xlenbits = match width { + BYTE => sign_extend(loaded[7..0]), + HALF => sign_extend(loaded[15..0]), + WORD => sign_extend(loaded[31..0]), + DOUBLE => loaded + }; + let wval : MemoryOpResult(bool) = match (width, sizeof(xlen)) { + (BYTE, _) => mem_write_value(addr, 1, result[7..0], true & true, true, true), + (HALF, _) => mem_write_value(addr, 2, result[15..0], true & true, true, true), + (WORD, _) => mem_write_value(addr, 4, result[31..0], true & true, true, true), + (DOUBLE, 64) => mem_write_value(addr, 8, result, true & true, true, true), + _ => internal_error(__FILE__, __LINE__, "Unexpected AMO width") + }; + match (wval) { + MemValue(true) => { X(rd) = rval; RETIRE_SUCCESS }, + MemValue(false) => { internal_error(__FILE__, __LINE__, "AMO got false from mem_write_value") }, + MemException(e) => { handle_mem_exception(vaddr, e); RETIRE_FAIL } + } + } + } + } + } + } + } + } + } + } else { + handle_illegal(); + RETIRE_FAIL + } + } + +# SPDX-SnippetEnd diff --git a/spec/std/isa/inst/Zabha/amomaxu.b.rl.yaml b/spec/std/isa/inst/Zabha/amomaxu.b.rl.yaml new file mode 100644 index 0000000000..5a5974da84 --- /dev/null +++ b/spec/std/isa/inst/Zabha/amomaxu.b.rl.yaml @@ -0,0 +1,139 @@ +# Copyright (c) Qualcomm Technologies, Inc. and/or its subsidiaries. + +# WARNING: This file is auto-generated from spec/std/isa/inst/Zaamo/amomaxu.SIZE.AQRL.layout# Copyright (c) Abhijit Das(Sukuna0007Abhi) +# SPDX-License-Identifier: BSD-3-Clause-Clear + +# yaml-language-server: $schema=../../../../schemas/inst_schema.json + +$schema: "inst_schema.json#" +kind: instruction +name: amomaxu.b.rl +long_name: Atomic MAX unsigned byte (release) +description: | + Atomically with release ordering: + + * Load the byte at address _xs1_ + * Write the sign-extended value into _xd_ + * Unsigned compare the least-significant byte of register _xs2_ to the loaded value, and select the maximum value + * Write the maximum to the address in _xs1_ +definedBy: Zabha +assembly: xd, xs2, (xs1) +encoding: + match: 1110001----------000-----0101111 + variables: + - name: xs2 + location: 24-20 + - name: xs1 + location: 19-15 + - name: xd + location: 11-7 +access: + s: always + u: always + vs: always + vu: always +operation(): | + if (!implemented?(ExtensionName::A) || (MISA_CSR_IMPLEMENTED && (CSR[misa].A == 1'b0))) { + raise (ExceptionCode::IllegalInstruction, mode(), $encoding); + } + + XReg virtual_address = X[xs1]; + X[xd] = amo<8>(virtual_address, X[xs2][7:0], AmoOperation::Maxu, 1'b0, 1'b1, $encoding); + + memory_model_release(); + +# SPDX-SnippetBegin +# SPDX-FileCopyrightText: 2017-2025 Contributors to the RISCV Sail Model +# SPDX-License-Identifier: BSD-2-Clause +sail(): | + { + if extension("A") then { + /* Get the address, X(rs1) (no offset). + * Some extensions perform additional checks on address validity. + */ + match ext_data_get_addr(rs1, zeros(), ReadWrite(Data, Data), width) { + Ext_DataAddr_Error(e) => { ext_handle_data_check_error(e); RETIRE_FAIL }, + Ext_DataAddr_OK(vaddr) => { + match translateAddr(vaddr, ReadWrite(Data, Data)) { + TR_Failure(e, _) => { handle_mem_exception(vaddr, e); RETIRE_FAIL }, + TR_Address(addr, _) => { + let eares : MemoryOpResult(unit) = match (width, sizeof(xlen)) { + (BYTE, _) => mem_write_ea(addr, 1, false & true, true, true), + (HALF, _) => mem_write_ea(addr, 2, false & true, true, true), + (WORD, _) => mem_write_ea(addr, 4, false & true, true, true), + (DOUBLE, 64) => mem_write_ea(addr, 8, false & true, true, true), + _ => internal_error(__FILE__, __LINE__, "Unexpected AMO width") + }; + let is_unsigned : bool = match op { + AMOMINU => true, + AMOMAXU => true, + _ => false + }; + let xs2_val : xlenbits = match width { + BYTE => if is_unsigned then zero_extend(X(rs2)[7..0]) else sign_extend(X(rs2)[7..0]), + HALF => if is_unsigned then zero_extend(X(rs2)[15..0]) else sign_extend(X(rs2)[15..0]), + WORD => if is_unsigned then zero_extend(X(rs2)[31..0]) else sign_extend(X(rs2)[31..0]), + DOUBLE => X(rs2) + }; + match (eares) { + MemException(e) => { handle_mem_exception(vaddr, e); RETIRE_FAIL }, + MemValue(_) => { + let mval : MemoryOpResult(xlenbits) = match (width, sizeof(xlen)) { + (BYTE, _) => extend_value(is_unsigned, mem_read(ReadWrite(Data, Data), addr, 1, false, false & true, true)), + (HALF, _) => extend_value(is_unsigned, mem_read(ReadWrite(Data, Data), addr, 2, false, false & true, true)), + (WORD, _) => extend_value(is_unsigned, mem_read(ReadWrite(Data, Data), addr, 4, false, false & true, true)), + (DOUBLE, 64) => extend_value(is_unsigned, mem_read(ReadWrite(Data, Data), addr, 8, false, false & true, true)), + _ => internal_error(__FILE__, __LINE__, "Unexpected AMO width") + }; + match (mval) { + MemException(e) => { handle_mem_exception(vaddr, e); RETIRE_FAIL }, + MemValue(loaded) => { + let result : xlenbits = + match op { + AMOSWAP => xs2_val, + AMOADD => xs2_val + loaded, + AMOXOR => xs2_val ^ loaded, + AMOAND => xs2_val & loaded, + AMOOR => xs2_val | loaded, + + /* These operations convert bitvectors to integer values using [un]signed, + * and back using to_bits(). + */ + AMOMIN => to_bits(sizeof(xlen), min(signed(xs2_val), signed(loaded))), + AMOMAX => to_bits(sizeof(xlen), max(signed(xs2_val), signed(loaded))), + AMOMINU => to_bits(sizeof(xlen), min(unsigned(xs2_val), unsigned(loaded))), + AMOMAXU => to_bits(sizeof(xlen), max(unsigned(xs2_val), unsigned(loaded))) + }; + let rval : xlenbits = match width { + BYTE => sign_extend(loaded[7..0]), + HALF => sign_extend(loaded[15..0]), + WORD => sign_extend(loaded[31..0]), + DOUBLE => loaded + }; + let wval : MemoryOpResult(bool) = match (width, sizeof(xlen)) { + (BYTE, _) => mem_write_value(addr, 1, result[7..0], false & true, true, true), + (HALF, _) => mem_write_value(addr, 2, result[15..0], false & true, true, true), + (WORD, _) => mem_write_value(addr, 4, result[31..0], false & true, true, true), + (DOUBLE, 64) => mem_write_value(addr, 8, result, false & true, true, true), + _ => internal_error(__FILE__, __LINE__, "Unexpected AMO width") + }; + match (wval) { + MemValue(true) => { X(rd) = rval; RETIRE_SUCCESS }, + MemValue(false) => { internal_error(__FILE__, __LINE__, "AMO got false from mem_write_value") }, + MemException(e) => { handle_mem_exception(vaddr, e); RETIRE_FAIL } + } + } + } + } + } + } + } + } + } + } else { + handle_illegal(); + RETIRE_FAIL + } + } + +# SPDX-SnippetEnd diff --git a/spec/std/isa/inst/Zabha/amomaxu.b.yaml b/spec/std/isa/inst/Zabha/amomaxu.b.yaml index 503483b157..1742d42db3 100644 --- a/spec/std/isa/inst/Zabha/amomaxu.b.yaml +++ b/spec/std/isa/inst/Zabha/amomaxu.b.yaml @@ -1,4 +1,6 @@ # Copyright (c) Qualcomm Technologies, Inc. and/or its subsidiaries. + +# WARNING: This file is auto-generated from spec/std/isa/inst/Zaamo/amomaxu.SIZE.AQRL.layout# Copyright (c) Abhijit Das(Sukuna0007Abhi) # SPDX-License-Identifier: BSD-3-Clause-Clear # yaml-language-server: $schema=../../../../schemas/inst_schema.json @@ -6,18 +8,19 @@ $schema: "inst_schema.json#" kind: instruction name: amomaxu.b -long_name: No synopsis available +long_name: Atomic MAX unsigned byte description: | - No description available. + Atomically: + + * Load the byte at address _xs1_ + * Write the sign-extended value into _xd_ + * Unsigned compare the least-significant byte of register _xs2_ to the loaded value, and select the maximum value + * Write the maximum to the address in _xs1_ definedBy: Zabha assembly: xd, xs2, (xs1) encoding: - match: 11100------------000-----0101111 + match: 1110000----------000-----0101111 variables: - - name: aq - location: 26-26 - - name: rl - location: 25-25 - name: xs2 location: 24-20 - name: xs1 @@ -29,8 +32,13 @@ access: u: always vs: always vu: always -data_independent_timing: false operation(): | + if (!implemented?(ExtensionName::A) || (MISA_CSR_IMPLEMENTED && (CSR[misa].A == 1'b0))) { + raise (ExceptionCode::IllegalInstruction, mode(), $encoding); + } + + XReg virtual_address = X[xs1]; + X[xd] = amo<8>(virtual_address, X[xs2][7:0], AmoOperation::Maxu, 1'b0, 1'b0, $encoding); # SPDX-SnippetBegin # SPDX-FileCopyrightText: 2017-2025 Contributors to the RISCV Sail Model @@ -48,10 +56,10 @@ sail(): | TR_Failure(e, _) => { handle_mem_exception(vaddr, e); RETIRE_FAIL }, TR_Address(addr, _) => { let eares : MemoryOpResult(unit) = match (width, sizeof(xlen)) { - (BYTE, _) => mem_write_ea(addr, 1, aq & rl, rl, true), - (HALF, _) => mem_write_ea(addr, 2, aq & rl, rl, true), - (WORD, _) => mem_write_ea(addr, 4, aq & rl, rl, true), - (DOUBLE, 64) => mem_write_ea(addr, 8, aq & rl, rl, true), + (BYTE, _) => mem_write_ea(addr, 1, false & false, false, true), + (HALF, _) => mem_write_ea(addr, 2, false & false, false, true), + (WORD, _) => mem_write_ea(addr, 4, false & false, false, true), + (DOUBLE, 64) => mem_write_ea(addr, 8, false & false, false, true), _ => internal_error(__FILE__, __LINE__, "Unexpected AMO width") }; let is_unsigned : bool = match op { @@ -59,7 +67,7 @@ sail(): | AMOMAXU => true, _ => false }; - let rs2_val : xlenbits = match width { + let xs2_val : xlenbits = match width { BYTE => if is_unsigned then zero_extend(X(rs2)[7..0]) else sign_extend(X(rs2)[7..0]), HALF => if is_unsigned then zero_extend(X(rs2)[15..0]) else sign_extend(X(rs2)[15..0]), WORD => if is_unsigned then zero_extend(X(rs2)[31..0]) else sign_extend(X(rs2)[31..0]), @@ -69,10 +77,10 @@ sail(): | MemException(e) => { handle_mem_exception(vaddr, e); RETIRE_FAIL }, MemValue(_) => { let mval : MemoryOpResult(xlenbits) = match (width, sizeof(xlen)) { - (BYTE, _) => extend_value(is_unsigned, mem_read(ReadWrite(Data, Data), addr, 1, aq, aq & rl, true)), - (HALF, _) => extend_value(is_unsigned, mem_read(ReadWrite(Data, Data), addr, 2, aq, aq & rl, true)), - (WORD, _) => extend_value(is_unsigned, mem_read(ReadWrite(Data, Data), addr, 4, aq, aq & rl, true)), - (DOUBLE, 64) => extend_value(is_unsigned, mem_read(ReadWrite(Data, Data), addr, 8, aq, aq & rl, true)), + (BYTE, _) => extend_value(is_unsigned, mem_read(ReadWrite(Data, Data), addr, 1, false, false & false, true)), + (HALF, _) => extend_value(is_unsigned, mem_read(ReadWrite(Data, Data), addr, 2, false, false & false, true)), + (WORD, _) => extend_value(is_unsigned, mem_read(ReadWrite(Data, Data), addr, 4, false, false & false, true)), + (DOUBLE, 64) => extend_value(is_unsigned, mem_read(ReadWrite(Data, Data), addr, 8, false, false & false, true)), _ => internal_error(__FILE__, __LINE__, "Unexpected AMO width") }; match (mval) { @@ -80,19 +88,19 @@ sail(): | MemValue(loaded) => { let result : xlenbits = match op { - AMOSWAP => rs2_val, - AMOADD => rs2_val + loaded, - AMOXOR => rs2_val ^ loaded, - AMOAND => rs2_val & loaded, - AMOOR => rs2_val | loaded, + AMOSWAP => xs2_val, + AMOADD => xs2_val + loaded, + AMOXOR => xs2_val ^ loaded, + AMOAND => xs2_val & loaded, + AMOOR => xs2_val | loaded, /* These operations convert bitvectors to integer values using [un]signed, * and back using to_bits(). */ - AMOMIN => to_bits(sizeof(xlen), min(signed(rs2_val), signed(loaded))), - AMOMAX => to_bits(sizeof(xlen), max(signed(rs2_val), signed(loaded))), - AMOMINU => to_bits(sizeof(xlen), min(unsigned(rs2_val), unsigned(loaded))), - AMOMAXU => to_bits(sizeof(xlen), max(unsigned(rs2_val), unsigned(loaded))) + AMOMIN => to_bits(sizeof(xlen), min(signed(xs2_val), signed(loaded))), + AMOMAX => to_bits(sizeof(xlen), max(signed(xs2_val), signed(loaded))), + AMOMINU => to_bits(sizeof(xlen), min(unsigned(xs2_val), unsigned(loaded))), + AMOMAXU => to_bits(sizeof(xlen), max(unsigned(xs2_val), unsigned(loaded))) }; let rval : xlenbits = match width { BYTE => sign_extend(loaded[7..0]), @@ -101,10 +109,10 @@ sail(): | DOUBLE => loaded }; let wval : MemoryOpResult(bool) = match (width, sizeof(xlen)) { - (BYTE, _) => mem_write_value(addr, 1, result[7..0], aq & rl, rl, true), - (HALF, _) => mem_write_value(addr, 2, result[15..0], aq & rl, rl, true), - (WORD, _) => mem_write_value(addr, 4, result[31..0], aq & rl, rl, true), - (DOUBLE, 64) => mem_write_value(addr, 8, result, aq & rl, rl, true), + (BYTE, _) => mem_write_value(addr, 1, result[7..0], false & false, false, true), + (HALF, _) => mem_write_value(addr, 2, result[15..0], false & false, false, true), + (WORD, _) => mem_write_value(addr, 4, result[31..0], false & false, false, true), + (DOUBLE, 64) => mem_write_value(addr, 8, result, false & false, false, true), _ => internal_error(__FILE__, __LINE__, "Unexpected AMO width") }; match (wval) { diff --git a/spec/std/isa/inst/Zabha/amomaxu.h.aq.yaml b/spec/std/isa/inst/Zabha/amomaxu.h.aq.yaml new file mode 100644 index 0000000000..a0328abbb7 --- /dev/null +++ b/spec/std/isa/inst/Zabha/amomaxu.h.aq.yaml @@ -0,0 +1,139 @@ +# Copyright (c) Qualcomm Technologies, Inc. and/or its subsidiaries. + +# WARNING: This file is auto-generated from spec/std/isa/inst/Zaamo/amomaxu.SIZE.AQRL.layout# Copyright (c) Abhijit Das(Sukuna0007Abhi) +# SPDX-License-Identifier: BSD-3-Clause-Clear + +# yaml-language-server: $schema=../../../../schemas/inst_schema.json + +$schema: "inst_schema.json#" +kind: instruction +name: amomaxu.h.aq +long_name: Atomic MAX unsigned halfword (acquire) +description: | + Atomically with acquire ordering: + + * Load the halfword at address _xs1_ + * Write the sign-extended value into _xd_ + * Unsigned compare the least-significant halfword of register _xs2_ to the loaded value, and select the maximum value + * Write the maximum to the address in _xs1_ +definedBy: Zabha +assembly: xd, xs2, (xs1) +encoding: + match: 1110010----------001-----0101111 + variables: + - name: xs2 + location: 24-20 + - name: xs1 + location: 19-15 + - name: xd + location: 11-7 +access: + s: always + u: always + vs: always + vu: always +operation(): | + if (!implemented?(ExtensionName::A) || (MISA_CSR_IMPLEMENTED && (CSR[misa].A == 1'b0))) { + raise (ExceptionCode::IllegalInstruction, mode(), $encoding); + } + + memory_model_acquire(); + + XReg virtual_address = X[xs1]; + X[xd] = amo<16>(virtual_address, X[xs2][15:0], AmoOperation::Maxu, 1'b1, 1'b0, $encoding); + +# SPDX-SnippetBegin +# SPDX-FileCopyrightText: 2017-2025 Contributors to the RISCV Sail Model +# SPDX-License-Identifier: BSD-2-Clause +sail(): | + { + if extension("A") then { + /* Get the address, X(rs1) (no offset). + * Some extensions perform additional checks on address validity. + */ + match ext_data_get_addr(rs1, zeros(), ReadWrite(Data, Data), width) { + Ext_DataAddr_Error(e) => { ext_handle_data_check_error(e); RETIRE_FAIL }, + Ext_DataAddr_OK(vaddr) => { + match translateAddr(vaddr, ReadWrite(Data, Data)) { + TR_Failure(e, _) => { handle_mem_exception(vaddr, e); RETIRE_FAIL }, + TR_Address(addr, _) => { + let eares : MemoryOpResult(unit) = match (width, sizeof(xlen)) { + (BYTE, _) => mem_write_ea(addr, 1, true & false, false, true), + (HALF, _) => mem_write_ea(addr, 2, true & false, false, true), + (WORD, _) => mem_write_ea(addr, 4, true & false, false, true), + (DOUBLE, 64) => mem_write_ea(addr, 8, true & false, false, true), + _ => internal_error(__FILE__, __LINE__, "Unexpected AMO width") + }; + let is_unsigned : bool = match op { + AMOMINU => true, + AMOMAXU => true, + _ => false + }; + let xs2_val : xlenbits = match width { + BYTE => if is_unsigned then zero_extend(X(rs2)[7..0]) else sign_extend(X(rs2)[7..0]), + HALF => if is_unsigned then zero_extend(X(rs2)[15..0]) else sign_extend(X(rs2)[15..0]), + WORD => if is_unsigned then zero_extend(X(rs2)[31..0]) else sign_extend(X(rs2)[31..0]), + DOUBLE => X(rs2) + }; + match (eares) { + MemException(e) => { handle_mem_exception(vaddr, e); RETIRE_FAIL }, + MemValue(_) => { + let mval : MemoryOpResult(xlenbits) = match (width, sizeof(xlen)) { + (BYTE, _) => extend_value(is_unsigned, mem_read(ReadWrite(Data, Data), addr, 1, true, true & false, true)), + (HALF, _) => extend_value(is_unsigned, mem_read(ReadWrite(Data, Data), addr, 2, true, true & false, true)), + (WORD, _) => extend_value(is_unsigned, mem_read(ReadWrite(Data, Data), addr, 4, true, true & false, true)), + (DOUBLE, 64) => extend_value(is_unsigned, mem_read(ReadWrite(Data, Data), addr, 8, true, true & false, true)), + _ => internal_error(__FILE__, __LINE__, "Unexpected AMO width") + }; + match (mval) { + MemException(e) => { handle_mem_exception(vaddr, e); RETIRE_FAIL }, + MemValue(loaded) => { + let result : xlenbits = + match op { + AMOSWAP => xs2_val, + AMOADD => xs2_val + loaded, + AMOXOR => xs2_val ^ loaded, + AMOAND => xs2_val & loaded, + AMOOR => xs2_val | loaded, + + /* These operations convert bitvectors to integer values using [un]signed, + * and back using to_bits(). + */ + AMOMIN => to_bits(sizeof(xlen), min(signed(xs2_val), signed(loaded))), + AMOMAX => to_bits(sizeof(xlen), max(signed(xs2_val), signed(loaded))), + AMOMINU => to_bits(sizeof(xlen), min(unsigned(xs2_val), unsigned(loaded))), + AMOMAXU => to_bits(sizeof(xlen), max(unsigned(xs2_val), unsigned(loaded))) + }; + let rval : xlenbits = match width { + BYTE => sign_extend(loaded[7..0]), + HALF => sign_extend(loaded[15..0]), + WORD => sign_extend(loaded[31..0]), + DOUBLE => loaded + }; + let wval : MemoryOpResult(bool) = match (width, sizeof(xlen)) { + (BYTE, _) => mem_write_value(addr, 1, result[7..0], true & false, false, true), + (HALF, _) => mem_write_value(addr, 2, result[15..0], true & false, false, true), + (WORD, _) => mem_write_value(addr, 4, result[31..0], true & false, false, true), + (DOUBLE, 64) => mem_write_value(addr, 8, result, true & false, false, true), + _ => internal_error(__FILE__, __LINE__, "Unexpected AMO width") + }; + match (wval) { + MemValue(true) => { X(rd) = rval; RETIRE_SUCCESS }, + MemValue(false) => { internal_error(__FILE__, __LINE__, "AMO got false from mem_write_value") }, + MemException(e) => { handle_mem_exception(vaddr, e); RETIRE_FAIL } + } + } + } + } + } + } + } + } + } + } else { + handle_illegal(); + RETIRE_FAIL + } + } + +# SPDX-SnippetEnd diff --git a/spec/std/isa/inst/Zabha/amomaxu.h.aqrl.yaml b/spec/std/isa/inst/Zabha/amomaxu.h.aqrl.yaml new file mode 100644 index 0000000000..bcafffd526 --- /dev/null +++ b/spec/std/isa/inst/Zabha/amomaxu.h.aqrl.yaml @@ -0,0 +1,141 @@ +# Copyright (c) Qualcomm Technologies, Inc. and/or its subsidiaries. + +# WARNING: This file is auto-generated from spec/std/isa/inst/Zaamo/amomaxu.SIZE.AQRL.layout# Copyright (c) Abhijit Das(Sukuna0007Abhi) +# SPDX-License-Identifier: BSD-3-Clause-Clear + +# yaml-language-server: $schema=../../../../schemas/inst_schema.json + +$schema: "inst_schema.json#" +kind: instruction +name: amomaxu.h.aqrl +long_name: Atomic MAX unsigned halfword (acquire-release) +description: | + Atomically with acquire and release ordering: + + * Load the halfword at address _xs1_ + * Write the sign-extended value into _xd_ + * Unsigned compare the least-significant halfword of register _xs2_ to the loaded value, and select the maximum value + * Write the maximum to the address in _xs1_ +definedBy: Zabha +assembly: xd, xs2, (xs1) +encoding: + match: 1110011----------001-----0101111 + variables: + - name: xs2 + location: 24-20 + - name: xs1 + location: 19-15 + - name: xd + location: 11-7 +access: + s: always + u: always + vs: always + vu: always +operation(): | + if (!implemented?(ExtensionName::A) || (MISA_CSR_IMPLEMENTED && (CSR[misa].A == 1'b0))) { + raise (ExceptionCode::IllegalInstruction, mode(), $encoding); + } + + memory_model_acquire(); + + XReg virtual_address = X[xs1]; + X[xd] = amo<16>(virtual_address, X[xs2][15:0], AmoOperation::Maxu, 1'b1, 1'b1, $encoding); + + memory_model_release(); + +# SPDX-SnippetBegin +# SPDX-FileCopyrightText: 2017-2025 Contributors to the RISCV Sail Model +# SPDX-License-Identifier: BSD-2-Clause +sail(): | + { + if extension("A") then { + /* Get the address, X(rs1) (no offset). + * Some extensions perform additional checks on address validity. + */ + match ext_data_get_addr(rs1, zeros(), ReadWrite(Data, Data), width) { + Ext_DataAddr_Error(e) => { ext_handle_data_check_error(e); RETIRE_FAIL }, + Ext_DataAddr_OK(vaddr) => { + match translateAddr(vaddr, ReadWrite(Data, Data)) { + TR_Failure(e, _) => { handle_mem_exception(vaddr, e); RETIRE_FAIL }, + TR_Address(addr, _) => { + let eares : MemoryOpResult(unit) = match (width, sizeof(xlen)) { + (BYTE, _) => mem_write_ea(addr, 1, true & true, true, true), + (HALF, _) => mem_write_ea(addr, 2, true & true, true, true), + (WORD, _) => mem_write_ea(addr, 4, true & true, true, true), + (DOUBLE, 64) => mem_write_ea(addr, 8, true & true, true, true), + _ => internal_error(__FILE__, __LINE__, "Unexpected AMO width") + }; + let is_unsigned : bool = match op { + AMOMINU => true, + AMOMAXU => true, + _ => false + }; + let xs2_val : xlenbits = match width { + BYTE => if is_unsigned then zero_extend(X(rs2)[7..0]) else sign_extend(X(rs2)[7..0]), + HALF => if is_unsigned then zero_extend(X(rs2)[15..0]) else sign_extend(X(rs2)[15..0]), + WORD => if is_unsigned then zero_extend(X(rs2)[31..0]) else sign_extend(X(rs2)[31..0]), + DOUBLE => X(rs2) + }; + match (eares) { + MemException(e) => { handle_mem_exception(vaddr, e); RETIRE_FAIL }, + MemValue(_) => { + let mval : MemoryOpResult(xlenbits) = match (width, sizeof(xlen)) { + (BYTE, _) => extend_value(is_unsigned, mem_read(ReadWrite(Data, Data), addr, 1, true, true & true, true)), + (HALF, _) => extend_value(is_unsigned, mem_read(ReadWrite(Data, Data), addr, 2, true, true & true, true)), + (WORD, _) => extend_value(is_unsigned, mem_read(ReadWrite(Data, Data), addr, 4, true, true & true, true)), + (DOUBLE, 64) => extend_value(is_unsigned, mem_read(ReadWrite(Data, Data), addr, 8, true, true & true, true)), + _ => internal_error(__FILE__, __LINE__, "Unexpected AMO width") + }; + match (mval) { + MemException(e) => { handle_mem_exception(vaddr, e); RETIRE_FAIL }, + MemValue(loaded) => { + let result : xlenbits = + match op { + AMOSWAP => xs2_val, + AMOADD => xs2_val + loaded, + AMOXOR => xs2_val ^ loaded, + AMOAND => xs2_val & loaded, + AMOOR => xs2_val | loaded, + + /* These operations convert bitvectors to integer values using [un]signed, + * and back using to_bits(). + */ + AMOMIN => to_bits(sizeof(xlen), min(signed(xs2_val), signed(loaded))), + AMOMAX => to_bits(sizeof(xlen), max(signed(xs2_val), signed(loaded))), + AMOMINU => to_bits(sizeof(xlen), min(unsigned(xs2_val), unsigned(loaded))), + AMOMAXU => to_bits(sizeof(xlen), max(unsigned(xs2_val), unsigned(loaded))) + }; + let rval : xlenbits = match width { + BYTE => sign_extend(loaded[7..0]), + HALF => sign_extend(loaded[15..0]), + WORD => sign_extend(loaded[31..0]), + DOUBLE => loaded + }; + let wval : MemoryOpResult(bool) = match (width, sizeof(xlen)) { + (BYTE, _) => mem_write_value(addr, 1, result[7..0], true & true, true, true), + (HALF, _) => mem_write_value(addr, 2, result[15..0], true & true, true, true), + (WORD, _) => mem_write_value(addr, 4, result[31..0], true & true, true, true), + (DOUBLE, 64) => mem_write_value(addr, 8, result, true & true, true, true), + _ => internal_error(__FILE__, __LINE__, "Unexpected AMO width") + }; + match (wval) { + MemValue(true) => { X(rd) = rval; RETIRE_SUCCESS }, + MemValue(false) => { internal_error(__FILE__, __LINE__, "AMO got false from mem_write_value") }, + MemException(e) => { handle_mem_exception(vaddr, e); RETIRE_FAIL } + } + } + } + } + } + } + } + } + } + } else { + handle_illegal(); + RETIRE_FAIL + } + } + +# SPDX-SnippetEnd diff --git a/spec/std/isa/inst/Zabha/amomaxu.h.rl.yaml b/spec/std/isa/inst/Zabha/amomaxu.h.rl.yaml new file mode 100644 index 0000000000..9cc0f41174 --- /dev/null +++ b/spec/std/isa/inst/Zabha/amomaxu.h.rl.yaml @@ -0,0 +1,139 @@ +# Copyright (c) Qualcomm Technologies, Inc. and/or its subsidiaries. + +# WARNING: This file is auto-generated from spec/std/isa/inst/Zaamo/amomaxu.SIZE.AQRL.layout# Copyright (c) Abhijit Das(Sukuna0007Abhi) +# SPDX-License-Identifier: BSD-3-Clause-Clear + +# yaml-language-server: $schema=../../../../schemas/inst_schema.json + +$schema: "inst_schema.json#" +kind: instruction +name: amomaxu.h.rl +long_name: Atomic MAX unsigned halfword (release) +description: | + Atomically with release ordering: + + * Load the halfword at address _xs1_ + * Write the sign-extended value into _xd_ + * Unsigned compare the least-significant halfword of register _xs2_ to the loaded value, and select the maximum value + * Write the maximum to the address in _xs1_ +definedBy: Zabha +assembly: xd, xs2, (xs1) +encoding: + match: 1110001----------001-----0101111 + variables: + - name: xs2 + location: 24-20 + - name: xs1 + location: 19-15 + - name: xd + location: 11-7 +access: + s: always + u: always + vs: always + vu: always +operation(): | + if (!implemented?(ExtensionName::A) || (MISA_CSR_IMPLEMENTED && (CSR[misa].A == 1'b0))) { + raise (ExceptionCode::IllegalInstruction, mode(), $encoding); + } + + XReg virtual_address = X[xs1]; + X[xd] = amo<16>(virtual_address, X[xs2][15:0], AmoOperation::Maxu, 1'b0, 1'b1, $encoding); + + memory_model_release(); + +# SPDX-SnippetBegin +# SPDX-FileCopyrightText: 2017-2025 Contributors to the RISCV Sail Model +# SPDX-License-Identifier: BSD-2-Clause +sail(): | + { + if extension("A") then { + /* Get the address, X(rs1) (no offset). + * Some extensions perform additional checks on address validity. + */ + match ext_data_get_addr(rs1, zeros(), ReadWrite(Data, Data), width) { + Ext_DataAddr_Error(e) => { ext_handle_data_check_error(e); RETIRE_FAIL }, + Ext_DataAddr_OK(vaddr) => { + match translateAddr(vaddr, ReadWrite(Data, Data)) { + TR_Failure(e, _) => { handle_mem_exception(vaddr, e); RETIRE_FAIL }, + TR_Address(addr, _) => { + let eares : MemoryOpResult(unit) = match (width, sizeof(xlen)) { + (BYTE, _) => mem_write_ea(addr, 1, false & true, true, true), + (HALF, _) => mem_write_ea(addr, 2, false & true, true, true), + (WORD, _) => mem_write_ea(addr, 4, false & true, true, true), + (DOUBLE, 64) => mem_write_ea(addr, 8, false & true, true, true), + _ => internal_error(__FILE__, __LINE__, "Unexpected AMO width") + }; + let is_unsigned : bool = match op { + AMOMINU => true, + AMOMAXU => true, + _ => false + }; + let xs2_val : xlenbits = match width { + BYTE => if is_unsigned then zero_extend(X(rs2)[7..0]) else sign_extend(X(rs2)[7..0]), + HALF => if is_unsigned then zero_extend(X(rs2)[15..0]) else sign_extend(X(rs2)[15..0]), + WORD => if is_unsigned then zero_extend(X(rs2)[31..0]) else sign_extend(X(rs2)[31..0]), + DOUBLE => X(rs2) + }; + match (eares) { + MemException(e) => { handle_mem_exception(vaddr, e); RETIRE_FAIL }, + MemValue(_) => { + let mval : MemoryOpResult(xlenbits) = match (width, sizeof(xlen)) { + (BYTE, _) => extend_value(is_unsigned, mem_read(ReadWrite(Data, Data), addr, 1, false, false & true, true)), + (HALF, _) => extend_value(is_unsigned, mem_read(ReadWrite(Data, Data), addr, 2, false, false & true, true)), + (WORD, _) => extend_value(is_unsigned, mem_read(ReadWrite(Data, Data), addr, 4, false, false & true, true)), + (DOUBLE, 64) => extend_value(is_unsigned, mem_read(ReadWrite(Data, Data), addr, 8, false, false & true, true)), + _ => internal_error(__FILE__, __LINE__, "Unexpected AMO width") + }; + match (mval) { + MemException(e) => { handle_mem_exception(vaddr, e); RETIRE_FAIL }, + MemValue(loaded) => { + let result : xlenbits = + match op { + AMOSWAP => xs2_val, + AMOADD => xs2_val + loaded, + AMOXOR => xs2_val ^ loaded, + AMOAND => xs2_val & loaded, + AMOOR => xs2_val | loaded, + + /* These operations convert bitvectors to integer values using [un]signed, + * and back using to_bits(). + */ + AMOMIN => to_bits(sizeof(xlen), min(signed(xs2_val), signed(loaded))), + AMOMAX => to_bits(sizeof(xlen), max(signed(xs2_val), signed(loaded))), + AMOMINU => to_bits(sizeof(xlen), min(unsigned(xs2_val), unsigned(loaded))), + AMOMAXU => to_bits(sizeof(xlen), max(unsigned(xs2_val), unsigned(loaded))) + }; + let rval : xlenbits = match width { + BYTE => sign_extend(loaded[7..0]), + HALF => sign_extend(loaded[15..0]), + WORD => sign_extend(loaded[31..0]), + DOUBLE => loaded + }; + let wval : MemoryOpResult(bool) = match (width, sizeof(xlen)) { + (BYTE, _) => mem_write_value(addr, 1, result[7..0], false & true, true, true), + (HALF, _) => mem_write_value(addr, 2, result[15..0], false & true, true, true), + (WORD, _) => mem_write_value(addr, 4, result[31..0], false & true, true, true), + (DOUBLE, 64) => mem_write_value(addr, 8, result, false & true, true, true), + _ => internal_error(__FILE__, __LINE__, "Unexpected AMO width") + }; + match (wval) { + MemValue(true) => { X(rd) = rval; RETIRE_SUCCESS }, + MemValue(false) => { internal_error(__FILE__, __LINE__, "AMO got false from mem_write_value") }, + MemException(e) => { handle_mem_exception(vaddr, e); RETIRE_FAIL } + } + } + } + } + } + } + } + } + } + } else { + handle_illegal(); + RETIRE_FAIL + } + } + +# SPDX-SnippetEnd diff --git a/spec/std/isa/inst/Zabha/amomaxu.h.yaml b/spec/std/isa/inst/Zabha/amomaxu.h.yaml index 5c681db4ef..c16ec09d05 100644 --- a/spec/std/isa/inst/Zabha/amomaxu.h.yaml +++ b/spec/std/isa/inst/Zabha/amomaxu.h.yaml @@ -1,4 +1,6 @@ # Copyright (c) Qualcomm Technologies, Inc. and/or its subsidiaries. + +# WARNING: This file is auto-generated from spec/std/isa/inst/Zaamo/amomaxu.SIZE.AQRL.layout# Copyright (c) Abhijit Das(Sukuna0007Abhi) # SPDX-License-Identifier: BSD-3-Clause-Clear # yaml-language-server: $schema=../../../../schemas/inst_schema.json @@ -6,18 +8,19 @@ $schema: "inst_schema.json#" kind: instruction name: amomaxu.h -long_name: No synopsis available +long_name: Atomic MAX unsigned halfword description: | - No description available. + Atomically: + + * Load the halfword at address _xs1_ + * Write the sign-extended value into _xd_ + * Unsigned compare the least-significant halfword of register _xs2_ to the loaded value, and select the maximum value + * Write the maximum to the address in _xs1_ definedBy: Zabha assembly: xd, xs2, (xs1) encoding: - match: 11100------------001-----0101111 + match: 1110000----------001-----0101111 variables: - - name: aq - location: 26-26 - - name: rl - location: 25-25 - name: xs2 location: 24-20 - name: xs1 @@ -29,8 +32,13 @@ access: u: always vs: always vu: always -data_independent_timing: false operation(): | + if (!implemented?(ExtensionName::A) || (MISA_CSR_IMPLEMENTED && (CSR[misa].A == 1'b0))) { + raise (ExceptionCode::IllegalInstruction, mode(), $encoding); + } + + XReg virtual_address = X[xs1]; + X[xd] = amo<16>(virtual_address, X[xs2][15:0], AmoOperation::Maxu, 1'b0, 1'b0, $encoding); # SPDX-SnippetBegin # SPDX-FileCopyrightText: 2017-2025 Contributors to the RISCV Sail Model @@ -48,10 +56,10 @@ sail(): | TR_Failure(e, _) => { handle_mem_exception(vaddr, e); RETIRE_FAIL }, TR_Address(addr, _) => { let eares : MemoryOpResult(unit) = match (width, sizeof(xlen)) { - (BYTE, _) => mem_write_ea(addr, 1, aq & rl, rl, true), - (HALF, _) => mem_write_ea(addr, 2, aq & rl, rl, true), - (WORD, _) => mem_write_ea(addr, 4, aq & rl, rl, true), - (DOUBLE, 64) => mem_write_ea(addr, 8, aq & rl, rl, true), + (BYTE, _) => mem_write_ea(addr, 1, false & false, false, true), + (HALF, _) => mem_write_ea(addr, 2, false & false, false, true), + (WORD, _) => mem_write_ea(addr, 4, false & false, false, true), + (DOUBLE, 64) => mem_write_ea(addr, 8, false & false, false, true), _ => internal_error(__FILE__, __LINE__, "Unexpected AMO width") }; let is_unsigned : bool = match op { @@ -59,7 +67,7 @@ sail(): | AMOMAXU => true, _ => false }; - let rs2_val : xlenbits = match width { + let xs2_val : xlenbits = match width { BYTE => if is_unsigned then zero_extend(X(rs2)[7..0]) else sign_extend(X(rs2)[7..0]), HALF => if is_unsigned then zero_extend(X(rs2)[15..0]) else sign_extend(X(rs2)[15..0]), WORD => if is_unsigned then zero_extend(X(rs2)[31..0]) else sign_extend(X(rs2)[31..0]), @@ -69,10 +77,10 @@ sail(): | MemException(e) => { handle_mem_exception(vaddr, e); RETIRE_FAIL }, MemValue(_) => { let mval : MemoryOpResult(xlenbits) = match (width, sizeof(xlen)) { - (BYTE, _) => extend_value(is_unsigned, mem_read(ReadWrite(Data, Data), addr, 1, aq, aq & rl, true)), - (HALF, _) => extend_value(is_unsigned, mem_read(ReadWrite(Data, Data), addr, 2, aq, aq & rl, true)), - (WORD, _) => extend_value(is_unsigned, mem_read(ReadWrite(Data, Data), addr, 4, aq, aq & rl, true)), - (DOUBLE, 64) => extend_value(is_unsigned, mem_read(ReadWrite(Data, Data), addr, 8, aq, aq & rl, true)), + (BYTE, _) => extend_value(is_unsigned, mem_read(ReadWrite(Data, Data), addr, 1, false, false & false, true)), + (HALF, _) => extend_value(is_unsigned, mem_read(ReadWrite(Data, Data), addr, 2, false, false & false, true)), + (WORD, _) => extend_value(is_unsigned, mem_read(ReadWrite(Data, Data), addr, 4, false, false & false, true)), + (DOUBLE, 64) => extend_value(is_unsigned, mem_read(ReadWrite(Data, Data), addr, 8, false, false & false, true)), _ => internal_error(__FILE__, __LINE__, "Unexpected AMO width") }; match (mval) { @@ -80,19 +88,19 @@ sail(): | MemValue(loaded) => { let result : xlenbits = match op { - AMOSWAP => rs2_val, - AMOADD => rs2_val + loaded, - AMOXOR => rs2_val ^ loaded, - AMOAND => rs2_val & loaded, - AMOOR => rs2_val | loaded, + AMOSWAP => xs2_val, + AMOADD => xs2_val + loaded, + AMOXOR => xs2_val ^ loaded, + AMOAND => xs2_val & loaded, + AMOOR => xs2_val | loaded, /* These operations convert bitvectors to integer values using [un]signed, * and back using to_bits(). */ - AMOMIN => to_bits(sizeof(xlen), min(signed(rs2_val), signed(loaded))), - AMOMAX => to_bits(sizeof(xlen), max(signed(rs2_val), signed(loaded))), - AMOMINU => to_bits(sizeof(xlen), min(unsigned(rs2_val), unsigned(loaded))), - AMOMAXU => to_bits(sizeof(xlen), max(unsigned(rs2_val), unsigned(loaded))) + AMOMIN => to_bits(sizeof(xlen), min(signed(xs2_val), signed(loaded))), + AMOMAX => to_bits(sizeof(xlen), max(signed(xs2_val), signed(loaded))), + AMOMINU => to_bits(sizeof(xlen), min(unsigned(xs2_val), unsigned(loaded))), + AMOMAXU => to_bits(sizeof(xlen), max(unsigned(xs2_val), unsigned(loaded))) }; let rval : xlenbits = match width { BYTE => sign_extend(loaded[7..0]), @@ -101,10 +109,10 @@ sail(): | DOUBLE => loaded }; let wval : MemoryOpResult(bool) = match (width, sizeof(xlen)) { - (BYTE, _) => mem_write_value(addr, 1, result[7..0], aq & rl, rl, true), - (HALF, _) => mem_write_value(addr, 2, result[15..0], aq & rl, rl, true), - (WORD, _) => mem_write_value(addr, 4, result[31..0], aq & rl, rl, true), - (DOUBLE, 64) => mem_write_value(addr, 8, result, aq & rl, rl, true), + (BYTE, _) => mem_write_value(addr, 1, result[7..0], false & false, false, true), + (HALF, _) => mem_write_value(addr, 2, result[15..0], false & false, false, true), + (WORD, _) => mem_write_value(addr, 4, result[31..0], false & false, false, true), + (DOUBLE, 64) => mem_write_value(addr, 8, result, false & false, false, true), _ => internal_error(__FILE__, __LINE__, "Unexpected AMO width") }; match (wval) { diff --git a/spec/std/isa/inst/Zabha/amomin.b.aq.yaml b/spec/std/isa/inst/Zabha/amomin.b.aq.yaml new file mode 100644 index 0000000000..2785070a35 --- /dev/null +++ b/spec/std/isa/inst/Zabha/amomin.b.aq.yaml @@ -0,0 +1,139 @@ +# Copyright (c) Qualcomm Technologies, Inc. and/or its subsidiaries. + +# WARNING: This file is auto-generated from spec/std/isa/inst/Zaamo/amomin.SIZE.AQRL.layout# Copyright (c) Abhijit Das(Sukuna0007Abhi) +# SPDX-License-Identifier: BSD-3-Clause-Clear + +# yaml-language-server: $schema=../../../../schemas/inst_schema.json + +$schema: "inst_schema.json#" +kind: instruction +name: amomin.b.aq +long_name: Atomic MIN byte (acquire) +description: | + Atomically with acquire ordering: + + * Load the byte at address _xs1_ + * Write the sign-extended value into _xd_ + * Signed compare the least-significant byte of register _xs2_ to the loaded value, and select the minimum value + * Write the minimum to the address in _xs1_ +definedBy: Zabha +assembly: xd, xs2, (xs1) +encoding: + match: 1000010----------000-----0101111 + variables: + - name: xs2 + location: 24-20 + - name: xs1 + location: 19-15 + - name: xd + location: 11-7 +access: + s: always + u: always + vs: always + vu: always +operation(): | + if (!implemented?(ExtensionName::A) || (MISA_CSR_IMPLEMENTED && (CSR[misa].A == 1'b0))) { + raise (ExceptionCode::IllegalInstruction, mode(), $encoding); + } + + memory_model_acquire(); + + XReg virtual_address = X[xs1]; + X[xd] = amo<8>(virtual_address, X[xs2][7:0], AmoOperation::Min, 1'b1, 1'b0, $encoding); + +# SPDX-SnippetBegin +# SPDX-FileCopyrightText: 2017-2025 Contributors to the RISCV Sail Model +# SPDX-License-Identifier: BSD-2-Clause +sail(): | + { + if extension("A") then { + /* Get the address, X(rs1) (no offset). + * Some extensions perform additional checks on address validity. + */ + match ext_data_get_addr(rs1, zeros(), ReadWrite(Data, Data), width) { + Ext_DataAddr_Error(e) => { ext_handle_data_check_error(e); RETIRE_FAIL }, + Ext_DataAddr_OK(vaddr) => { + match translateAddr(vaddr, ReadWrite(Data, Data)) { + TR_Failure(e, _) => { handle_mem_exception(vaddr, e); RETIRE_FAIL }, + TR_Address(addr, _) => { + let eares : MemoryOpResult(unit) = match (width, sizeof(xlen)) { + (BYTE, _) => mem_write_ea(addr, 1, aq & rl, rl, true), + (HALF, _) => mem_write_ea(addr, 2, aq & rl, rl, true), + (WORD, _) => mem_write_ea(addr, 4, aq & rl, rl, true), + (DOUBLE, 64) => mem_write_ea(addr, 8, aq & rl, rl, true), + _ => internal_error(__FILE__, __LINE__, "Unexpected AMO width") + }; + let is_unsigned : bool = match op { + AMOMINU => true, + AMOMAXU => true, + _ => false + }; + let rs2_val : xlenbits = match width { + BYTE => if is_unsigned then zero_extend(X(rs2)[7..0]) else sign_extend(X(rs2)[7..0]), + HALF => if is_unsigned then zero_extend(X(rs2)[15..0]) else sign_extend(X(rs2)[15..0]), + WORD => if is_unsigned then zero_extend(X(rs2)[31..0]) else sign_extend(X(rs2)[31..0]), + DOUBLE => X(rs2) + }; + match (eares) { + MemException(e) => { handle_mem_exception(vaddr, e); RETIRE_FAIL }, + MemValue(_) => { + let mval : MemoryOpResult(xlenbits) = match (width, sizeof(xlen)) { + (BYTE, _) => extend_value(is_unsigned, mem_read(ReadWrite(Data, Data), addr, 1, aq, aq & rl, true)), + (HALF, _) => extend_value(is_unsigned, mem_read(ReadWrite(Data, Data), addr, 2, aq, aq & rl, true)), + (WORD, _) => extend_value(is_unsigned, mem_read(ReadWrite(Data, Data), addr, 4, aq, aq & rl, true)), + (DOUBLE, 64) => extend_value(is_unsigned, mem_read(ReadWrite(Data, Data), addr, 8, aq, aq & rl, true)), + _ => internal_error(__FILE__, __LINE__, "Unexpected AMO width") + }; + match (mval) { + MemException(e) => { handle_mem_exception(vaddr, e); RETIRE_FAIL }, + MemValue(loaded) => { + let result : xlenbits = + match op { + AMOSWAP => rs2_val, + AMOADD => rs2_val + loaded, + AMOXOR => rs2_val ^ loaded, + AMOAND => rs2_val & loaded, + AMOOR => rs2_val | loaded, + + /* These operations convert bitvectors to integer values using [un]signed, + * and back using to_bits(). + */ + AMOMIN => to_bits(sizeof(xlen), min(signed(rs2_val), signed(loaded))), + AMOMAX => to_bits(sizeof(xlen), max(signed(rs2_val), signed(loaded))), + AMOMINU => to_bits(sizeof(xlen), min(unsigned(rs2_val), unsigned(loaded))), + AMOMAXU => to_bits(sizeof(xlen), max(unsigned(rs2_val), unsigned(loaded))) + }; + let rval : xlenbits = match width { + BYTE => sign_extend(loaded[7..0]), + HALF => sign_extend(loaded[15..0]), + WORD => sign_extend(loaded[31..0]), + DOUBLE => loaded + }; + let wval : MemoryOpResult(bool) = match (width, sizeof(xlen)) { + (BYTE, _) => mem_write_value(addr, 1, result[7..0], aq & rl, rl, true), + (HALF, _) => mem_write_value(addr, 2, result[15..0], aq & rl, rl, true), + (WORD, _) => mem_write_value(addr, 4, result[31..0], aq & rl, rl, true), + (DOUBLE, 64) => mem_write_value(addr, 8, result, aq & rl, rl, true), + _ => internal_error(__FILE__, __LINE__, "Unexpected AMO width") + }; + match (wval) { + MemValue(true) => { X(rd) = rval; RETIRE_SUCCESS }, + MemValue(false) => { internal_error(__FILE__, __LINE__, "AMO got false from mem_write_value") }, + MemException(e) => { handle_mem_exception(vaddr, e); RETIRE_FAIL } + } + } + } + } + } + } + } + } + } + } else { + handle_illegal(); + RETIRE_FAIL + } + } + +# SPDX-SnippetEnd diff --git a/spec/std/isa/inst/Zabha/amomin.b.aqrl.yaml b/spec/std/isa/inst/Zabha/amomin.b.aqrl.yaml new file mode 100644 index 0000000000..49649658de --- /dev/null +++ b/spec/std/isa/inst/Zabha/amomin.b.aqrl.yaml @@ -0,0 +1,141 @@ +# Copyright (c) Qualcomm Technologies, Inc. and/or its subsidiaries. + +# WARNING: This file is auto-generated from spec/std/isa/inst/Zaamo/amomin.SIZE.AQRL.layout# Copyright (c) Abhijit Das(Sukuna0007Abhi) +# SPDX-License-Identifier: BSD-3-Clause-Clear + +# yaml-language-server: $schema=../../../../schemas/inst_schema.json + +$schema: "inst_schema.json#" +kind: instruction +name: amomin.b.aqrl +long_name: Atomic MIN byte (acquire-release) +description: | + Atomically with acquire and release ordering: + + * Load the byte at address _xs1_ + * Write the sign-extended value into _xd_ + * Signed compare the least-significant byte of register _xs2_ to the loaded value, and select the minimum value + * Write the minimum to the address in _xs1_ +definedBy: Zabha +assembly: xd, xs2, (xs1) +encoding: + match: 1000011----------000-----0101111 + variables: + - name: xs2 + location: 24-20 + - name: xs1 + location: 19-15 + - name: xd + location: 11-7 +access: + s: always + u: always + vs: always + vu: always +operation(): | + if (!implemented?(ExtensionName::A) || (MISA_CSR_IMPLEMENTED && (CSR[misa].A == 1'b0))) { + raise (ExceptionCode::IllegalInstruction, mode(), $encoding); + } + + memory_model_acquire(); + + XReg virtual_address = X[xs1]; + X[xd] = amo<8>(virtual_address, X[xs2][7:0], AmoOperation::Min, 1'b1, 1'b1, $encoding); + + memory_model_release(); + +# SPDX-SnippetBegin +# SPDX-FileCopyrightText: 2017-2025 Contributors to the RISCV Sail Model +# SPDX-License-Identifier: BSD-2-Clause +sail(): | + { + if extension("A") then { + /* Get the address, X(rs1) (no offset). + * Some extensions perform additional checks on address validity. + */ + match ext_data_get_addr(rs1, zeros(), ReadWrite(Data, Data), width) { + Ext_DataAddr_Error(e) => { ext_handle_data_check_error(e); RETIRE_FAIL }, + Ext_DataAddr_OK(vaddr) => { + match translateAddr(vaddr, ReadWrite(Data, Data)) { + TR_Failure(e, _) => { handle_mem_exception(vaddr, e); RETIRE_FAIL }, + TR_Address(addr, _) => { + let eares : MemoryOpResult(unit) = match (width, sizeof(xlen)) { + (BYTE, _) => mem_write_ea(addr, 1, aq & rl, rl, true), + (HALF, _) => mem_write_ea(addr, 2, aq & rl, rl, true), + (WORD, _) => mem_write_ea(addr, 4, aq & rl, rl, true), + (DOUBLE, 64) => mem_write_ea(addr, 8, aq & rl, rl, true), + _ => internal_error(__FILE__, __LINE__, "Unexpected AMO width") + }; + let is_unsigned : bool = match op { + AMOMINU => true, + AMOMAXU => true, + _ => false + }; + let rs2_val : xlenbits = match width { + BYTE => if is_unsigned then zero_extend(X(rs2)[7..0]) else sign_extend(X(rs2)[7..0]), + HALF => if is_unsigned then zero_extend(X(rs2)[15..0]) else sign_extend(X(rs2)[15..0]), + WORD => if is_unsigned then zero_extend(X(rs2)[31..0]) else sign_extend(X(rs2)[31..0]), + DOUBLE => X(rs2) + }; + match (eares) { + MemException(e) => { handle_mem_exception(vaddr, e); RETIRE_FAIL }, + MemValue(_) => { + let mval : MemoryOpResult(xlenbits) = match (width, sizeof(xlen)) { + (BYTE, _) => extend_value(is_unsigned, mem_read(ReadWrite(Data, Data), addr, 1, aq, aq & rl, true)), + (HALF, _) => extend_value(is_unsigned, mem_read(ReadWrite(Data, Data), addr, 2, aq, aq & rl, true)), + (WORD, _) => extend_value(is_unsigned, mem_read(ReadWrite(Data, Data), addr, 4, aq, aq & rl, true)), + (DOUBLE, 64) => extend_value(is_unsigned, mem_read(ReadWrite(Data, Data), addr, 8, aq, aq & rl, true)), + _ => internal_error(__FILE__, __LINE__, "Unexpected AMO width") + }; + match (mval) { + MemException(e) => { handle_mem_exception(vaddr, e); RETIRE_FAIL }, + MemValue(loaded) => { + let result : xlenbits = + match op { + AMOSWAP => rs2_val, + AMOADD => rs2_val + loaded, + AMOXOR => rs2_val ^ loaded, + AMOAND => rs2_val & loaded, + AMOOR => rs2_val | loaded, + + /* These operations convert bitvectors to integer values using [un]signed, + * and back using to_bits(). + */ + AMOMIN => to_bits(sizeof(xlen), min(signed(rs2_val), signed(loaded))), + AMOMAX => to_bits(sizeof(xlen), max(signed(rs2_val), signed(loaded))), + AMOMINU => to_bits(sizeof(xlen), min(unsigned(rs2_val), unsigned(loaded))), + AMOMAXU => to_bits(sizeof(xlen), max(unsigned(rs2_val), unsigned(loaded))) + }; + let rval : xlenbits = match width { + BYTE => sign_extend(loaded[7..0]), + HALF => sign_extend(loaded[15..0]), + WORD => sign_extend(loaded[31..0]), + DOUBLE => loaded + }; + let wval : MemoryOpResult(bool) = match (width, sizeof(xlen)) { + (BYTE, _) => mem_write_value(addr, 1, result[7..0], aq & rl, rl, true), + (HALF, _) => mem_write_value(addr, 2, result[15..0], aq & rl, rl, true), + (WORD, _) => mem_write_value(addr, 4, result[31..0], aq & rl, rl, true), + (DOUBLE, 64) => mem_write_value(addr, 8, result, aq & rl, rl, true), + _ => internal_error(__FILE__, __LINE__, "Unexpected AMO width") + }; + match (wval) { + MemValue(true) => { X(rd) = rval; RETIRE_SUCCESS }, + MemValue(false) => { internal_error(__FILE__, __LINE__, "AMO got false from mem_write_value") }, + MemException(e) => { handle_mem_exception(vaddr, e); RETIRE_FAIL } + } + } + } + } + } + } + } + } + } + } else { + handle_illegal(); + RETIRE_FAIL + } + } + +# SPDX-SnippetEnd diff --git a/spec/std/isa/inst/Zabha/amomin.b.rl.yaml b/spec/std/isa/inst/Zabha/amomin.b.rl.yaml new file mode 100644 index 0000000000..894b3c7551 --- /dev/null +++ b/spec/std/isa/inst/Zabha/amomin.b.rl.yaml @@ -0,0 +1,139 @@ +# Copyright (c) Qualcomm Technologies, Inc. and/or its subsidiaries. + +# WARNING: This file is auto-generated from spec/std/isa/inst/Zaamo/amomin.SIZE.AQRL.layout# Copyright (c) Abhijit Das(Sukuna0007Abhi) +# SPDX-License-Identifier: BSD-3-Clause-Clear + +# yaml-language-server: $schema=../../../../schemas/inst_schema.json + +$schema: "inst_schema.json#" +kind: instruction +name: amomin.b.rl +long_name: Atomic MIN byte (release) +description: | + Atomically with release ordering: + + * Load the byte at address _xs1_ + * Write the sign-extended value into _xd_ + * Signed compare the least-significant byte of register _xs2_ to the loaded value, and select the minimum value + * Write the minimum to the address in _xs1_ +definedBy: Zabha +assembly: xd, xs2, (xs1) +encoding: + match: 1000001----------000-----0101111 + variables: + - name: xs2 + location: 24-20 + - name: xs1 + location: 19-15 + - name: xd + location: 11-7 +access: + s: always + u: always + vs: always + vu: always +operation(): | + if (!implemented?(ExtensionName::A) || (MISA_CSR_IMPLEMENTED && (CSR[misa].A == 1'b0))) { + raise (ExceptionCode::IllegalInstruction, mode(), $encoding); + } + + XReg virtual_address = X[xs1]; + X[xd] = amo<8>(virtual_address, X[xs2][7:0], AmoOperation::Min, 1'b0, 1'b1, $encoding); + + memory_model_release(); + +# SPDX-SnippetBegin +# SPDX-FileCopyrightText: 2017-2025 Contributors to the RISCV Sail Model +# SPDX-License-Identifier: BSD-2-Clause +sail(): | + { + if extension("A") then { + /* Get the address, X(rs1) (no offset). + * Some extensions perform additional checks on address validity. + */ + match ext_data_get_addr(rs1, zeros(), ReadWrite(Data, Data), width) { + Ext_DataAddr_Error(e) => { ext_handle_data_check_error(e); RETIRE_FAIL }, + Ext_DataAddr_OK(vaddr) => { + match translateAddr(vaddr, ReadWrite(Data, Data)) { + TR_Failure(e, _) => { handle_mem_exception(vaddr, e); RETIRE_FAIL }, + TR_Address(addr, _) => { + let eares : MemoryOpResult(unit) = match (width, sizeof(xlen)) { + (BYTE, _) => mem_write_ea(addr, 1, aq & rl, rl, true), + (HALF, _) => mem_write_ea(addr, 2, aq & rl, rl, true), + (WORD, _) => mem_write_ea(addr, 4, aq & rl, rl, true), + (DOUBLE, 64) => mem_write_ea(addr, 8, aq & rl, rl, true), + _ => internal_error(__FILE__, __LINE__, "Unexpected AMO width") + }; + let is_unsigned : bool = match op { + AMOMINU => true, + AMOMAXU => true, + _ => false + }; + let rs2_val : xlenbits = match width { + BYTE => if is_unsigned then zero_extend(X(rs2)[7..0]) else sign_extend(X(rs2)[7..0]), + HALF => if is_unsigned then zero_extend(X(rs2)[15..0]) else sign_extend(X(rs2)[15..0]), + WORD => if is_unsigned then zero_extend(X(rs2)[31..0]) else sign_extend(X(rs2)[31..0]), + DOUBLE => X(rs2) + }; + match (eares) { + MemException(e) => { handle_mem_exception(vaddr, e); RETIRE_FAIL }, + MemValue(_) => { + let mval : MemoryOpResult(xlenbits) = match (width, sizeof(xlen)) { + (BYTE, _) => extend_value(is_unsigned, mem_read(ReadWrite(Data, Data), addr, 1, aq, aq & rl, true)), + (HALF, _) => extend_value(is_unsigned, mem_read(ReadWrite(Data, Data), addr, 2, aq, aq & rl, true)), + (WORD, _) => extend_value(is_unsigned, mem_read(ReadWrite(Data, Data), addr, 4, aq, aq & rl, true)), + (DOUBLE, 64) => extend_value(is_unsigned, mem_read(ReadWrite(Data, Data), addr, 8, aq, aq & rl, true)), + _ => internal_error(__FILE__, __LINE__, "Unexpected AMO width") + }; + match (mval) { + MemException(e) => { handle_mem_exception(vaddr, e); RETIRE_FAIL }, + MemValue(loaded) => { + let result : xlenbits = + match op { + AMOSWAP => rs2_val, + AMOADD => rs2_val + loaded, + AMOXOR => rs2_val ^ loaded, + AMOAND => rs2_val & loaded, + AMOOR => rs2_val | loaded, + + /* These operations convert bitvectors to integer values using [un]signed, + * and back using to_bits(). + */ + AMOMIN => to_bits(sizeof(xlen), min(signed(rs2_val), signed(loaded))), + AMOMAX => to_bits(sizeof(xlen), max(signed(rs2_val), signed(loaded))), + AMOMINU => to_bits(sizeof(xlen), min(unsigned(rs2_val), unsigned(loaded))), + AMOMAXU => to_bits(sizeof(xlen), max(unsigned(rs2_val), unsigned(loaded))) + }; + let rval : xlenbits = match width { + BYTE => sign_extend(loaded[7..0]), + HALF => sign_extend(loaded[15..0]), + WORD => sign_extend(loaded[31..0]), + DOUBLE => loaded + }; + let wval : MemoryOpResult(bool) = match (width, sizeof(xlen)) { + (BYTE, _) => mem_write_value(addr, 1, result[7..0], aq & rl, rl, true), + (HALF, _) => mem_write_value(addr, 2, result[15..0], aq & rl, rl, true), + (WORD, _) => mem_write_value(addr, 4, result[31..0], aq & rl, rl, true), + (DOUBLE, 64) => mem_write_value(addr, 8, result, aq & rl, rl, true), + _ => internal_error(__FILE__, __LINE__, "Unexpected AMO width") + }; + match (wval) { + MemValue(true) => { X(rd) = rval; RETIRE_SUCCESS }, + MemValue(false) => { internal_error(__FILE__, __LINE__, "AMO got false from mem_write_value") }, + MemException(e) => { handle_mem_exception(vaddr, e); RETIRE_FAIL } + } + } + } + } + } + } + } + } + } + } else { + handle_illegal(); + RETIRE_FAIL + } + } + +# SPDX-SnippetEnd diff --git a/spec/std/isa/inst/Zabha/amomin.b.yaml b/spec/std/isa/inst/Zabha/amomin.b.yaml index 227b4dba51..779e39a6ba 100644 --- a/spec/std/isa/inst/Zabha/amomin.b.yaml +++ b/spec/std/isa/inst/Zabha/amomin.b.yaml @@ -1,4 +1,6 @@ # Copyright (c) Qualcomm Technologies, Inc. and/or its subsidiaries. + +# WARNING: This file is auto-generated from spec/std/isa/inst/Zaamo/amomin.SIZE.AQRL.layout# Copyright (c) Abhijit Das(Sukuna0007Abhi) # SPDX-License-Identifier: BSD-3-Clause-Clear # yaml-language-server: $schema=../../../../schemas/inst_schema.json @@ -6,18 +8,19 @@ $schema: "inst_schema.json#" kind: instruction name: amomin.b -long_name: No synopsis available +long_name: Atomic MIN byte description: | - No description available. + Atomically: + + * Load the byte at address _xs1_ + * Write the sign-extended value into _xd_ + * Signed compare the least-significant byte of register _xs2_ to the loaded value, and select the minimum value + * Write the minimum to the address in _xs1_ definedBy: Zabha assembly: xd, xs2, (xs1) encoding: - match: 10000------------000-----0101111 + match: 1000000----------000-----0101111 variables: - - name: aq - location: 26-26 - - name: rl - location: 25-25 - name: xs2 location: 24-20 - name: xs1 @@ -29,8 +32,13 @@ access: u: always vs: always vu: always -data_independent_timing: false operation(): | + if (!implemented?(ExtensionName::A) || (MISA_CSR_IMPLEMENTED && (CSR[misa].A == 1'b0))) { + raise (ExceptionCode::IllegalInstruction, mode(), $encoding); + } + + XReg virtual_address = X[xs1]; + X[xd] = amo<8>(virtual_address, X[xs2][7:0], AmoOperation::Min, 1'b0, 1'b0, $encoding); # SPDX-SnippetBegin # SPDX-FileCopyrightText: 2017-2025 Contributors to the RISCV Sail Model diff --git a/spec/std/isa/inst/Zabha/amomin.h.aq.yaml b/spec/std/isa/inst/Zabha/amomin.h.aq.yaml new file mode 100644 index 0000000000..a3c559cde1 --- /dev/null +++ b/spec/std/isa/inst/Zabha/amomin.h.aq.yaml @@ -0,0 +1,139 @@ +# Copyright (c) Qualcomm Technologies, Inc. and/or its subsidiaries. + +# WARNING: This file is auto-generated from spec/std/isa/inst/Zaamo/amomin.SIZE.AQRL.layout# Copyright (c) Abhijit Das(Sukuna0007Abhi) +# SPDX-License-Identifier: BSD-3-Clause-Clear + +# yaml-language-server: $schema=../../../../schemas/inst_schema.json + +$schema: "inst_schema.json#" +kind: instruction +name: amomin.h.aq +long_name: Atomic MIN halfword (acquire) +description: | + Atomically with acquire ordering: + + * Load the halfword at address _xs1_ + * Write the sign-extended value into _xd_ + * Signed compare the least-significant halfword of register _xs2_ to the loaded value, and select the minimum value + * Write the minimum to the address in _xs1_ +definedBy: Zabha +assembly: xd, xs2, (xs1) +encoding: + match: 1000010----------001-----0101111 + variables: + - name: xs2 + location: 24-20 + - name: xs1 + location: 19-15 + - name: xd + location: 11-7 +access: + s: always + u: always + vs: always + vu: always +operation(): | + if (!implemented?(ExtensionName::A) || (MISA_CSR_IMPLEMENTED && (CSR[misa].A == 1'b0))) { + raise (ExceptionCode::IllegalInstruction, mode(), $encoding); + } + + memory_model_acquire(); + + XReg virtual_address = X[xs1]; + X[xd] = amo<16>(virtual_address, X[xs2][15:0], AmoOperation::Min, 1'b1, 1'b0, $encoding); + +# SPDX-SnippetBegin +# SPDX-FileCopyrightText: 2017-2025 Contributors to the RISCV Sail Model +# SPDX-License-Identifier: BSD-2-Clause +sail(): | + { + if extension("A") then { + /* Get the address, X(rs1) (no offset). + * Some extensions perform additional checks on address validity. + */ + match ext_data_get_addr(rs1, zeros(), ReadWrite(Data, Data), width) { + Ext_DataAddr_Error(e) => { ext_handle_data_check_error(e); RETIRE_FAIL }, + Ext_DataAddr_OK(vaddr) => { + match translateAddr(vaddr, ReadWrite(Data, Data)) { + TR_Failure(e, _) => { handle_mem_exception(vaddr, e); RETIRE_FAIL }, + TR_Address(addr, _) => { + let eares : MemoryOpResult(unit) = match (width, sizeof(xlen)) { + (BYTE, _) => mem_write_ea(addr, 1, aq & rl, rl, true), + (HALF, _) => mem_write_ea(addr, 2, aq & rl, rl, true), + (WORD, _) => mem_write_ea(addr, 4, aq & rl, rl, true), + (DOUBLE, 64) => mem_write_ea(addr, 8, aq & rl, rl, true), + _ => internal_error(__FILE__, __LINE__, "Unexpected AMO width") + }; + let is_unsigned : bool = match op { + AMOMINU => true, + AMOMAXU => true, + _ => false + }; + let rs2_val : xlenbits = match width { + BYTE => if is_unsigned then zero_extend(X(rs2)[7..0]) else sign_extend(X(rs2)[7..0]), + HALF => if is_unsigned then zero_extend(X(rs2)[15..0]) else sign_extend(X(rs2)[15..0]), + WORD => if is_unsigned then zero_extend(X(rs2)[31..0]) else sign_extend(X(rs2)[31..0]), + DOUBLE => X(rs2) + }; + match (eares) { + MemException(e) => { handle_mem_exception(vaddr, e); RETIRE_FAIL }, + MemValue(_) => { + let mval : MemoryOpResult(xlenbits) = match (width, sizeof(xlen)) { + (BYTE, _) => extend_value(is_unsigned, mem_read(ReadWrite(Data, Data), addr, 1, aq, aq & rl, true)), + (HALF, _) => extend_value(is_unsigned, mem_read(ReadWrite(Data, Data), addr, 2, aq, aq & rl, true)), + (WORD, _) => extend_value(is_unsigned, mem_read(ReadWrite(Data, Data), addr, 4, aq, aq & rl, true)), + (DOUBLE, 64) => extend_value(is_unsigned, mem_read(ReadWrite(Data, Data), addr, 8, aq, aq & rl, true)), + _ => internal_error(__FILE__, __LINE__, "Unexpected AMO width") + }; + match (mval) { + MemException(e) => { handle_mem_exception(vaddr, e); RETIRE_FAIL }, + MemValue(loaded) => { + let result : xlenbits = + match op { + AMOSWAP => rs2_val, + AMOADD => rs2_val + loaded, + AMOXOR => rs2_val ^ loaded, + AMOAND => rs2_val & loaded, + AMOOR => rs2_val | loaded, + + /* These operations convert bitvectors to integer values using [un]signed, + * and back using to_bits(). + */ + AMOMIN => to_bits(sizeof(xlen), min(signed(rs2_val), signed(loaded))), + AMOMAX => to_bits(sizeof(xlen), max(signed(rs2_val), signed(loaded))), + AMOMINU => to_bits(sizeof(xlen), min(unsigned(rs2_val), unsigned(loaded))), + AMOMAXU => to_bits(sizeof(xlen), max(unsigned(rs2_val), unsigned(loaded))) + }; + let rval : xlenbits = match width { + BYTE => sign_extend(loaded[7..0]), + HALF => sign_extend(loaded[15..0]), + WORD => sign_extend(loaded[31..0]), + DOUBLE => loaded + }; + let wval : MemoryOpResult(bool) = match (width, sizeof(xlen)) { + (BYTE, _) => mem_write_value(addr, 1, result[7..0], aq & rl, rl, true), + (HALF, _) => mem_write_value(addr, 2, result[15..0], aq & rl, rl, true), + (WORD, _) => mem_write_value(addr, 4, result[31..0], aq & rl, rl, true), + (DOUBLE, 64) => mem_write_value(addr, 8, result, aq & rl, rl, true), + _ => internal_error(__FILE__, __LINE__, "Unexpected AMO width") + }; + match (wval) { + MemValue(true) => { X(rd) = rval; RETIRE_SUCCESS }, + MemValue(false) => { internal_error(__FILE__, __LINE__, "AMO got false from mem_write_value") }, + MemException(e) => { handle_mem_exception(vaddr, e); RETIRE_FAIL } + } + } + } + } + } + } + } + } + } + } else { + handle_illegal(); + RETIRE_FAIL + } + } + +# SPDX-SnippetEnd diff --git a/spec/std/isa/inst/Zabha/amomin.h.aqrl.yaml b/spec/std/isa/inst/Zabha/amomin.h.aqrl.yaml new file mode 100644 index 0000000000..147c68738e --- /dev/null +++ b/spec/std/isa/inst/Zabha/amomin.h.aqrl.yaml @@ -0,0 +1,141 @@ +# Copyright (c) Qualcomm Technologies, Inc. and/or its subsidiaries. + +# WARNING: This file is auto-generated from spec/std/isa/inst/Zaamo/amomin.SIZE.AQRL.layout# Copyright (c) Abhijit Das(Sukuna0007Abhi) +# SPDX-License-Identifier: BSD-3-Clause-Clear + +# yaml-language-server: $schema=../../../../schemas/inst_schema.json + +$schema: "inst_schema.json#" +kind: instruction +name: amomin.h.aqrl +long_name: Atomic MIN halfword (acquire-release) +description: | + Atomically with acquire and release ordering: + + * Load the halfword at address _xs1_ + * Write the sign-extended value into _xd_ + * Signed compare the least-significant halfword of register _xs2_ to the loaded value, and select the minimum value + * Write the minimum to the address in _xs1_ +definedBy: Zabha +assembly: xd, xs2, (xs1) +encoding: + match: 1000011----------001-----0101111 + variables: + - name: xs2 + location: 24-20 + - name: xs1 + location: 19-15 + - name: xd + location: 11-7 +access: + s: always + u: always + vs: always + vu: always +operation(): | + if (!implemented?(ExtensionName::A) || (MISA_CSR_IMPLEMENTED && (CSR[misa].A == 1'b0))) { + raise (ExceptionCode::IllegalInstruction, mode(), $encoding); + } + + memory_model_acquire(); + + XReg virtual_address = X[xs1]; + X[xd] = amo<16>(virtual_address, X[xs2][15:0], AmoOperation::Min, 1'b1, 1'b1, $encoding); + + memory_model_release(); + +# SPDX-SnippetBegin +# SPDX-FileCopyrightText: 2017-2025 Contributors to the RISCV Sail Model +# SPDX-License-Identifier: BSD-2-Clause +sail(): | + { + if extension("A") then { + /* Get the address, X(rs1) (no offset). + * Some extensions perform additional checks on address validity. + */ + match ext_data_get_addr(rs1, zeros(), ReadWrite(Data, Data), width) { + Ext_DataAddr_Error(e) => { ext_handle_data_check_error(e); RETIRE_FAIL }, + Ext_DataAddr_OK(vaddr) => { + match translateAddr(vaddr, ReadWrite(Data, Data)) { + TR_Failure(e, _) => { handle_mem_exception(vaddr, e); RETIRE_FAIL }, + TR_Address(addr, _) => { + let eares : MemoryOpResult(unit) = match (width, sizeof(xlen)) { + (BYTE, _) => mem_write_ea(addr, 1, aq & rl, rl, true), + (HALF, _) => mem_write_ea(addr, 2, aq & rl, rl, true), + (WORD, _) => mem_write_ea(addr, 4, aq & rl, rl, true), + (DOUBLE, 64) => mem_write_ea(addr, 8, aq & rl, rl, true), + _ => internal_error(__FILE__, __LINE__, "Unexpected AMO width") + }; + let is_unsigned : bool = match op { + AMOMINU => true, + AMOMAXU => true, + _ => false + }; + let rs2_val : xlenbits = match width { + BYTE => if is_unsigned then zero_extend(X(rs2)[7..0]) else sign_extend(X(rs2)[7..0]), + HALF => if is_unsigned then zero_extend(X(rs2)[15..0]) else sign_extend(X(rs2)[15..0]), + WORD => if is_unsigned then zero_extend(X(rs2)[31..0]) else sign_extend(X(rs2)[31..0]), + DOUBLE => X(rs2) + }; + match (eares) { + MemException(e) => { handle_mem_exception(vaddr, e); RETIRE_FAIL }, + MemValue(_) => { + let mval : MemoryOpResult(xlenbits) = match (width, sizeof(xlen)) { + (BYTE, _) => extend_value(is_unsigned, mem_read(ReadWrite(Data, Data), addr, 1, aq, aq & rl, true)), + (HALF, _) => extend_value(is_unsigned, mem_read(ReadWrite(Data, Data), addr, 2, aq, aq & rl, true)), + (WORD, _) => extend_value(is_unsigned, mem_read(ReadWrite(Data, Data), addr, 4, aq, aq & rl, true)), + (DOUBLE, 64) => extend_value(is_unsigned, mem_read(ReadWrite(Data, Data), addr, 8, aq, aq & rl, true)), + _ => internal_error(__FILE__, __LINE__, "Unexpected AMO width") + }; + match (mval) { + MemException(e) => { handle_mem_exception(vaddr, e); RETIRE_FAIL }, + MemValue(loaded) => { + let result : xlenbits = + match op { + AMOSWAP => rs2_val, + AMOADD => rs2_val + loaded, + AMOXOR => rs2_val ^ loaded, + AMOAND => rs2_val & loaded, + AMOOR => rs2_val | loaded, + + /* These operations convert bitvectors to integer values using [un]signed, + * and back using to_bits(). + */ + AMOMIN => to_bits(sizeof(xlen), min(signed(rs2_val), signed(loaded))), + AMOMAX => to_bits(sizeof(xlen), max(signed(rs2_val), signed(loaded))), + AMOMINU => to_bits(sizeof(xlen), min(unsigned(rs2_val), unsigned(loaded))), + AMOMAXU => to_bits(sizeof(xlen), max(unsigned(rs2_val), unsigned(loaded))) + }; + let rval : xlenbits = match width { + BYTE => sign_extend(loaded[7..0]), + HALF => sign_extend(loaded[15..0]), + WORD => sign_extend(loaded[31..0]), + DOUBLE => loaded + }; + let wval : MemoryOpResult(bool) = match (width, sizeof(xlen)) { + (BYTE, _) => mem_write_value(addr, 1, result[7..0], aq & rl, rl, true), + (HALF, _) => mem_write_value(addr, 2, result[15..0], aq & rl, rl, true), + (WORD, _) => mem_write_value(addr, 4, result[31..0], aq & rl, rl, true), + (DOUBLE, 64) => mem_write_value(addr, 8, result, aq & rl, rl, true), + _ => internal_error(__FILE__, __LINE__, "Unexpected AMO width") + }; + match (wval) { + MemValue(true) => { X(rd) = rval; RETIRE_SUCCESS }, + MemValue(false) => { internal_error(__FILE__, __LINE__, "AMO got false from mem_write_value") }, + MemException(e) => { handle_mem_exception(vaddr, e); RETIRE_FAIL } + } + } + } + } + } + } + } + } + } + } else { + handle_illegal(); + RETIRE_FAIL + } + } + +# SPDX-SnippetEnd diff --git a/spec/std/isa/inst/Zabha/amomin.h.rl.yaml b/spec/std/isa/inst/Zabha/amomin.h.rl.yaml new file mode 100644 index 0000000000..0b58befdea --- /dev/null +++ b/spec/std/isa/inst/Zabha/amomin.h.rl.yaml @@ -0,0 +1,139 @@ +# Copyright (c) Qualcomm Technologies, Inc. and/or its subsidiaries. + +# WARNING: This file is auto-generated from spec/std/isa/inst/Zaamo/amomin.SIZE.AQRL.layout# Copyright (c) Abhijit Das(Sukuna0007Abhi) +# SPDX-License-Identifier: BSD-3-Clause-Clear + +# yaml-language-server: $schema=../../../../schemas/inst_schema.json + +$schema: "inst_schema.json#" +kind: instruction +name: amomin.h.rl +long_name: Atomic MIN halfword (release) +description: | + Atomically with release ordering: + + * Load the halfword at address _xs1_ + * Write the sign-extended value into _xd_ + * Signed compare the least-significant halfword of register _xs2_ to the loaded value, and select the minimum value + * Write the minimum to the address in _xs1_ +definedBy: Zabha +assembly: xd, xs2, (xs1) +encoding: + match: 1000001----------001-----0101111 + variables: + - name: xs2 + location: 24-20 + - name: xs1 + location: 19-15 + - name: xd + location: 11-7 +access: + s: always + u: always + vs: always + vu: always +operation(): | + if (!implemented?(ExtensionName::A) || (MISA_CSR_IMPLEMENTED && (CSR[misa].A == 1'b0))) { + raise (ExceptionCode::IllegalInstruction, mode(), $encoding); + } + + XReg virtual_address = X[xs1]; + X[xd] = amo<16>(virtual_address, X[xs2][15:0], AmoOperation::Min, 1'b0, 1'b1, $encoding); + + memory_model_release(); + +# SPDX-SnippetBegin +# SPDX-FileCopyrightText: 2017-2025 Contributors to the RISCV Sail Model +# SPDX-License-Identifier: BSD-2-Clause +sail(): | + { + if extension("A") then { + /* Get the address, X(rs1) (no offset). + * Some extensions perform additional checks on address validity. + */ + match ext_data_get_addr(rs1, zeros(), ReadWrite(Data, Data), width) { + Ext_DataAddr_Error(e) => { ext_handle_data_check_error(e); RETIRE_FAIL }, + Ext_DataAddr_OK(vaddr) => { + match translateAddr(vaddr, ReadWrite(Data, Data)) { + TR_Failure(e, _) => { handle_mem_exception(vaddr, e); RETIRE_FAIL }, + TR_Address(addr, _) => { + let eares : MemoryOpResult(unit) = match (width, sizeof(xlen)) { + (BYTE, _) => mem_write_ea(addr, 1, aq & rl, rl, true), + (HALF, _) => mem_write_ea(addr, 2, aq & rl, rl, true), + (WORD, _) => mem_write_ea(addr, 4, aq & rl, rl, true), + (DOUBLE, 64) => mem_write_ea(addr, 8, aq & rl, rl, true), + _ => internal_error(__FILE__, __LINE__, "Unexpected AMO width") + }; + let is_unsigned : bool = match op { + AMOMINU => true, + AMOMAXU => true, + _ => false + }; + let rs2_val : xlenbits = match width { + BYTE => if is_unsigned then zero_extend(X(rs2)[7..0]) else sign_extend(X(rs2)[7..0]), + HALF => if is_unsigned then zero_extend(X(rs2)[15..0]) else sign_extend(X(rs2)[15..0]), + WORD => if is_unsigned then zero_extend(X(rs2)[31..0]) else sign_extend(X(rs2)[31..0]), + DOUBLE => X(rs2) + }; + match (eares) { + MemException(e) => { handle_mem_exception(vaddr, e); RETIRE_FAIL }, + MemValue(_) => { + let mval : MemoryOpResult(xlenbits) = match (width, sizeof(xlen)) { + (BYTE, _) => extend_value(is_unsigned, mem_read(ReadWrite(Data, Data), addr, 1, aq, aq & rl, true)), + (HALF, _) => extend_value(is_unsigned, mem_read(ReadWrite(Data, Data), addr, 2, aq, aq & rl, true)), + (WORD, _) => extend_value(is_unsigned, mem_read(ReadWrite(Data, Data), addr, 4, aq, aq & rl, true)), + (DOUBLE, 64) => extend_value(is_unsigned, mem_read(ReadWrite(Data, Data), addr, 8, aq, aq & rl, true)), + _ => internal_error(__FILE__, __LINE__, "Unexpected AMO width") + }; + match (mval) { + MemException(e) => { handle_mem_exception(vaddr, e); RETIRE_FAIL }, + MemValue(loaded) => { + let result : xlenbits = + match op { + AMOSWAP => rs2_val, + AMOADD => rs2_val + loaded, + AMOXOR => rs2_val ^ loaded, + AMOAND => rs2_val & loaded, + AMOOR => rs2_val | loaded, + + /* These operations convert bitvectors to integer values using [un]signed, + * and back using to_bits(). + */ + AMOMIN => to_bits(sizeof(xlen), min(signed(rs2_val), signed(loaded))), + AMOMAX => to_bits(sizeof(xlen), max(signed(rs2_val), signed(loaded))), + AMOMINU => to_bits(sizeof(xlen), min(unsigned(rs2_val), unsigned(loaded))), + AMOMAXU => to_bits(sizeof(xlen), max(unsigned(rs2_val), unsigned(loaded))) + }; + let rval : xlenbits = match width { + BYTE => sign_extend(loaded[7..0]), + HALF => sign_extend(loaded[15..0]), + WORD => sign_extend(loaded[31..0]), + DOUBLE => loaded + }; + let wval : MemoryOpResult(bool) = match (width, sizeof(xlen)) { + (BYTE, _) => mem_write_value(addr, 1, result[7..0], aq & rl, rl, true), + (HALF, _) => mem_write_value(addr, 2, result[15..0], aq & rl, rl, true), + (WORD, _) => mem_write_value(addr, 4, result[31..0], aq & rl, rl, true), + (DOUBLE, 64) => mem_write_value(addr, 8, result, aq & rl, rl, true), + _ => internal_error(__FILE__, __LINE__, "Unexpected AMO width") + }; + match (wval) { + MemValue(true) => { X(rd) = rval; RETIRE_SUCCESS }, + MemValue(false) => { internal_error(__FILE__, __LINE__, "AMO got false from mem_write_value") }, + MemException(e) => { handle_mem_exception(vaddr, e); RETIRE_FAIL } + } + } + } + } + } + } + } + } + } + } else { + handle_illegal(); + RETIRE_FAIL + } + } + +# SPDX-SnippetEnd diff --git a/spec/std/isa/inst/Zabha/amomin.h.yaml b/spec/std/isa/inst/Zabha/amomin.h.yaml index 4fba419578..14a4f6a833 100644 --- a/spec/std/isa/inst/Zabha/amomin.h.yaml +++ b/spec/std/isa/inst/Zabha/amomin.h.yaml @@ -1,4 +1,6 @@ # Copyright (c) Qualcomm Technologies, Inc. and/or its subsidiaries. + +# WARNING: This file is auto-generated from spec/std/isa/inst/Zaamo/amomin.SIZE.AQRL.layout# Copyright (c) Abhijit Das(Sukuna0007Abhi) # SPDX-License-Identifier: BSD-3-Clause-Clear # yaml-language-server: $schema=../../../../schemas/inst_schema.json @@ -6,18 +8,19 @@ $schema: "inst_schema.json#" kind: instruction name: amomin.h -long_name: No synopsis available +long_name: Atomic MIN halfword description: | - No description available. + Atomically: + + * Load the halfword at address _xs1_ + * Write the sign-extended value into _xd_ + * Signed compare the least-significant halfword of register _xs2_ to the loaded value, and select the minimum value + * Write the minimum to the address in _xs1_ definedBy: Zabha assembly: xd, xs2, (xs1) encoding: - match: 10000------------001-----0101111 + match: 1000000----------001-----0101111 variables: - - name: aq - location: 26-26 - - name: rl - location: 25-25 - name: xs2 location: 24-20 - name: xs1 @@ -29,8 +32,13 @@ access: u: always vs: always vu: always -data_independent_timing: false operation(): | + if (!implemented?(ExtensionName::A) || (MISA_CSR_IMPLEMENTED && (CSR[misa].A == 1'b0))) { + raise (ExceptionCode::IllegalInstruction, mode(), $encoding); + } + + XReg virtual_address = X[xs1]; + X[xd] = amo<16>(virtual_address, X[xs2][15:0], AmoOperation::Min, 1'b0, 1'b0, $encoding); # SPDX-SnippetBegin # SPDX-FileCopyrightText: 2017-2025 Contributors to the RISCV Sail Model diff --git a/spec/std/isa/inst/Zabha/amominu.b.aq.yaml b/spec/std/isa/inst/Zabha/amominu.b.aq.yaml new file mode 100644 index 0000000000..ae1b57c3b0 --- /dev/null +++ b/spec/std/isa/inst/Zabha/amominu.b.aq.yaml @@ -0,0 +1,139 @@ +# Copyright (c) Qualcomm Technologies, Inc. and/or its subsidiaries. + +# WARNING: This file is auto-generated from spec/std/isa/inst/Zaamo/amominu.SIZE.AQRL.layout# Copyright (c) Abhijit Das(Sukuna0007Abhi) +# SPDX-License-Identifier: BSD-3-Clause-Clear + +# yaml-language-server: $schema=../../../../schemas/inst_schema.json + +$schema: "inst_schema.json#" +kind: instruction +name: amominu.b.aq +long_name: Atomic MIN unsigned byte (acquire) +description: | + Atomically with acquire ordering: + + * Load the byte at address _xs1_ + * Write the sign-extended value into _xd_ + * Unsigned compare the least-significant byte of register _xs2_ to the loaded value, and select the minimum value + * Write the minimum to the address in _xs1_ +definedBy: Zabha +assembly: xd, xs2, (xs1) +encoding: + match: 1100010----------000-----0101111 + variables: + - name: xs2 + location: 24-20 + - name: xs1 + location: 19-15 + - name: xd + location: 11-7 +access: + s: always + u: always + vs: always + vu: always +operation(): | + if (!implemented?(ExtensionName::A) || (MISA_CSR_IMPLEMENTED && (CSR[misa].A == 1'b0))) { + raise (ExceptionCode::IllegalInstruction, mode(), $encoding); + } + + memory_model_acquire(); + + XReg virtual_address = X[xs1]; + X[xd] = amo<8>(virtual_address, X[xs2][7:0], AmoOperation::Minu, 1'b1, 1'b0, $encoding); + +# SPDX-SnippetBegin +# SPDX-FileCopyrightText: 2017-2025 Contributors to the RISCV Sail Model +# SPDX-License-Identifier: BSD-2-Clause +sail(): | + { + if extension("A") then { + /* Get the address, X(rs1) (no offset). + * Some extensions perform additional checks on address validity. + */ + match ext_data_get_addr(rs1, zeros(), ReadWrite(Data, Data), width) { + Ext_DataAddr_Error(e) => { ext_handle_data_check_error(e); RETIRE_FAIL }, + Ext_DataAddr_OK(vaddr) => { + match translateAddr(vaddr, ReadWrite(Data, Data)) { + TR_Failure(e, _) => { handle_mem_exception(vaddr, e); RETIRE_FAIL }, + TR_Address(addr, _) => { + let eares : MemoryOpResult(unit) = match (width, sizeof(xlen)) { + (BYTE, _) => mem_write_ea(addr, 1, aq & rl, rl, true), + (HALF, _) => mem_write_ea(addr, 2, aq & rl, rl, true), + (WORD, _) => mem_write_ea(addr, 4, aq & rl, rl, true), + (DOUBLE, 64) => mem_write_ea(addr, 8, aq & rl, rl, true), + _ => internal_error(__FILE__, __LINE__, "Unexpected AMO width") + }; + let is_unsigned : bool = match op { + AMOMINU => true, + AMOMAXU => true, + _ => false + }; + let rs2_val : xlenbits = match width { + BYTE => if is_unsigned then zero_extend(X(rs2)[7..0]) else sign_extend(X(rs2)[7..0]), + HALF => if is_unsigned then zero_extend(X(rs2)[15..0]) else sign_extend(X(rs2)[15..0]), + WORD => if is_unsigned then zero_extend(X(rs2)[31..0]) else sign_extend(X(rs2)[31..0]), + DOUBLE => X(rs2) + }; + match (eares) { + MemException(e) => { handle_mem_exception(vaddr, e); RETIRE_FAIL }, + MemValue(_) => { + let mval : MemoryOpResult(xlenbits) = match (width, sizeof(xlen)) { + (BYTE, _) => extend_value(is_unsigned, mem_read(ReadWrite(Data, Data), addr, 1, aq, aq & rl, true)), + (HALF, _) => extend_value(is_unsigned, mem_read(ReadWrite(Data, Data), addr, 2, aq, aq & rl, true)), + (WORD, _) => extend_value(is_unsigned, mem_read(ReadWrite(Data, Data), addr, 4, aq, aq & rl, true)), + (DOUBLE, 64) => extend_value(is_unsigned, mem_read(ReadWrite(Data, Data), addr, 8, aq, aq & rl, true)), + _ => internal_error(__FILE__, __LINE__, "Unexpected AMO width") + }; + match (mval) { + MemException(e) => { handle_mem_exception(vaddr, e); RETIRE_FAIL }, + MemValue(loaded) => { + let result : xlenbits = + match op { + AMOSWAP => rs2_val, + AMOADD => rs2_val + loaded, + AMOXOR => rs2_val ^ loaded, + AMOAND => rs2_val & loaded, + AMOOR => rs2_val | loaded, + + /* These operations convert bitvectors to integer values using [un]signed, + * and back using to_bits(). + */ + AMOMIN => to_bits(sizeof(xlen), min(signed(rs2_val), signed(loaded))), + AMOMAX => to_bits(sizeof(xlen), max(signed(rs2_val), signed(loaded))), + AMOMINU => to_bits(sizeof(xlen), min(unsigned(rs2_val), unsigned(loaded))), + AMOMAXU => to_bits(sizeof(xlen), max(unsigned(rs2_val), unsigned(loaded))) + }; + let rval : xlenbits = match width { + BYTE => sign_extend(loaded[7..0]), + HALF => sign_extend(loaded[15..0]), + WORD => sign_extend(loaded[31..0]), + DOUBLE => loaded + }; + let wval : MemoryOpResult(bool) = match (width, sizeof(xlen)) { + (BYTE, _) => mem_write_value(addr, 1, result[7..0], aq & rl, rl, true), + (HALF, _) => mem_write_value(addr, 2, result[15..0], aq & rl, rl, true), + (WORD, _) => mem_write_value(addr, 4, result[31..0], aq & rl, rl, true), + (DOUBLE, 64) => mem_write_value(addr, 8, result, aq & rl, rl, true), + _ => internal_error(__FILE__, __LINE__, "Unexpected AMO width") + }; + match (wval) { + MemValue(true) => { X(rd) = rval; RETIRE_SUCCESS }, + MemValue(false) => { internal_error(__FILE__, __LINE__, "AMO got false from mem_write_value") }, + MemException(e) => { handle_mem_exception(vaddr, e); RETIRE_FAIL } + } + } + } + } + } + } + } + } + } + } else { + handle_illegal(); + RETIRE_FAIL + } + } + +# SPDX-SnippetEnd diff --git a/spec/std/isa/inst/Zabha/amominu.b.aqrl.yaml b/spec/std/isa/inst/Zabha/amominu.b.aqrl.yaml new file mode 100644 index 0000000000..e5617cfc4f --- /dev/null +++ b/spec/std/isa/inst/Zabha/amominu.b.aqrl.yaml @@ -0,0 +1,141 @@ +# Copyright (c) Qualcomm Technologies, Inc. and/or its subsidiaries. + +# WARNING: This file is auto-generated from spec/std/isa/inst/Zaamo/amominu.SIZE.AQRL.layout# Copyright (c) Abhijit Das(Sukuna0007Abhi) +# SPDX-License-Identifier: BSD-3-Clause-Clear + +# yaml-language-server: $schema=../../../../schemas/inst_schema.json + +$schema: "inst_schema.json#" +kind: instruction +name: amominu.b.aqrl +long_name: Atomic MIN unsigned byte (acquire-release) +description: | + Atomically with acquire and release ordering: + + * Load the byte at address _xs1_ + * Write the sign-extended value into _xd_ + * Unsigned compare the least-significant byte of register _xs2_ to the loaded value, and select the minimum value + * Write the minimum to the address in _xs1_ +definedBy: Zabha +assembly: xd, xs2, (xs1) +encoding: + match: 1100011----------000-----0101111 + variables: + - name: xs2 + location: 24-20 + - name: xs1 + location: 19-15 + - name: xd + location: 11-7 +access: + s: always + u: always + vs: always + vu: always +operation(): | + if (!implemented?(ExtensionName::A) || (MISA_CSR_IMPLEMENTED && (CSR[misa].A == 1'b0))) { + raise (ExceptionCode::IllegalInstruction, mode(), $encoding); + } + + memory_model_acquire(); + + XReg virtual_address = X[xs1]; + X[xd] = amo<8>(virtual_address, X[xs2][7:0], AmoOperation::Minu, 1'b1, 1'b1, $encoding); + + memory_model_release(); + +# SPDX-SnippetBegin +# SPDX-FileCopyrightText: 2017-2025 Contributors to the RISCV Sail Model +# SPDX-License-Identifier: BSD-2-Clause +sail(): | + { + if extension("A") then { + /* Get the address, X(rs1) (no offset). + * Some extensions perform additional checks on address validity. + */ + match ext_data_get_addr(rs1, zeros(), ReadWrite(Data, Data), width) { + Ext_DataAddr_Error(e) => { ext_handle_data_check_error(e); RETIRE_FAIL }, + Ext_DataAddr_OK(vaddr) => { + match translateAddr(vaddr, ReadWrite(Data, Data)) { + TR_Failure(e, _) => { handle_mem_exception(vaddr, e); RETIRE_FAIL }, + TR_Address(addr, _) => { + let eares : MemoryOpResult(unit) = match (width, sizeof(xlen)) { + (BYTE, _) => mem_write_ea(addr, 1, aq & rl, rl, true), + (HALF, _) => mem_write_ea(addr, 2, aq & rl, rl, true), + (WORD, _) => mem_write_ea(addr, 4, aq & rl, rl, true), + (DOUBLE, 64) => mem_write_ea(addr, 8, aq & rl, rl, true), + _ => internal_error(__FILE__, __LINE__, "Unexpected AMO width") + }; + let is_unsigned : bool = match op { + AMOMINU => true, + AMOMAXU => true, + _ => false + }; + let rs2_val : xlenbits = match width { + BYTE => if is_unsigned then zero_extend(X(rs2)[7..0]) else sign_extend(X(rs2)[7..0]), + HALF => if is_unsigned then zero_extend(X(rs2)[15..0]) else sign_extend(X(rs2)[15..0]), + WORD => if is_unsigned then zero_extend(X(rs2)[31..0]) else sign_extend(X(rs2)[31..0]), + DOUBLE => X(rs2) + }; + match (eares) { + MemException(e) => { handle_mem_exception(vaddr, e); RETIRE_FAIL }, + MemValue(_) => { + let mval : MemoryOpResult(xlenbits) = match (width, sizeof(xlen)) { + (BYTE, _) => extend_value(is_unsigned, mem_read(ReadWrite(Data, Data), addr, 1, aq, aq & rl, true)), + (HALF, _) => extend_value(is_unsigned, mem_read(ReadWrite(Data, Data), addr, 2, aq, aq & rl, true)), + (WORD, _) => extend_value(is_unsigned, mem_read(ReadWrite(Data, Data), addr, 4, aq, aq & rl, true)), + (DOUBLE, 64) => extend_value(is_unsigned, mem_read(ReadWrite(Data, Data), addr, 8, aq, aq & rl, true)), + _ => internal_error(__FILE__, __LINE__, "Unexpected AMO width") + }; + match (mval) { + MemException(e) => { handle_mem_exception(vaddr, e); RETIRE_FAIL }, + MemValue(loaded) => { + let result : xlenbits = + match op { + AMOSWAP => rs2_val, + AMOADD => rs2_val + loaded, + AMOXOR => rs2_val ^ loaded, + AMOAND => rs2_val & loaded, + AMOOR => rs2_val | loaded, + + /* These operations convert bitvectors to integer values using [un]signed, + * and back using to_bits(). + */ + AMOMIN => to_bits(sizeof(xlen), min(signed(rs2_val), signed(loaded))), + AMOMAX => to_bits(sizeof(xlen), max(signed(rs2_val), signed(loaded))), + AMOMINU => to_bits(sizeof(xlen), min(unsigned(rs2_val), unsigned(loaded))), + AMOMAXU => to_bits(sizeof(xlen), max(unsigned(rs2_val), unsigned(loaded))) + }; + let rval : xlenbits = match width { + BYTE => sign_extend(loaded[7..0]), + HALF => sign_extend(loaded[15..0]), + WORD => sign_extend(loaded[31..0]), + DOUBLE => loaded + }; + let wval : MemoryOpResult(bool) = match (width, sizeof(xlen)) { + (BYTE, _) => mem_write_value(addr, 1, result[7..0], aq & rl, rl, true), + (HALF, _) => mem_write_value(addr, 2, result[15..0], aq & rl, rl, true), + (WORD, _) => mem_write_value(addr, 4, result[31..0], aq & rl, rl, true), + (DOUBLE, 64) => mem_write_value(addr, 8, result, aq & rl, rl, true), + _ => internal_error(__FILE__, __LINE__, "Unexpected AMO width") + }; + match (wval) { + MemValue(true) => { X(rd) = rval; RETIRE_SUCCESS }, + MemValue(false) => { internal_error(__FILE__, __LINE__, "AMO got false from mem_write_value") }, + MemException(e) => { handle_mem_exception(vaddr, e); RETIRE_FAIL } + } + } + } + } + } + } + } + } + } + } else { + handle_illegal(); + RETIRE_FAIL + } + } + +# SPDX-SnippetEnd diff --git a/spec/std/isa/inst/Zabha/amominu.b.rl.yaml b/spec/std/isa/inst/Zabha/amominu.b.rl.yaml new file mode 100644 index 0000000000..d7c68a4583 --- /dev/null +++ b/spec/std/isa/inst/Zabha/amominu.b.rl.yaml @@ -0,0 +1,139 @@ +# Copyright (c) Qualcomm Technologies, Inc. and/or its subsidiaries. + +# WARNING: This file is auto-generated from spec/std/isa/inst/Zaamo/amominu.SIZE.AQRL.layout# Copyright (c) Abhijit Das(Sukuna0007Abhi) +# SPDX-License-Identifier: BSD-3-Clause-Clear + +# yaml-language-server: $schema=../../../../schemas/inst_schema.json + +$schema: "inst_schema.json#" +kind: instruction +name: amominu.b.rl +long_name: Atomic MIN unsigned byte (release) +description: | + Atomically with release ordering: + + * Load the byte at address _xs1_ + * Write the sign-extended value into _xd_ + * Unsigned compare the least-significant byte of register _xs2_ to the loaded value, and select the minimum value + * Write the minimum to the address in _xs1_ +definedBy: Zabha +assembly: xd, xs2, (xs1) +encoding: + match: 1100001----------000-----0101111 + variables: + - name: xs2 + location: 24-20 + - name: xs1 + location: 19-15 + - name: xd + location: 11-7 +access: + s: always + u: always + vs: always + vu: always +operation(): | + if (!implemented?(ExtensionName::A) || (MISA_CSR_IMPLEMENTED && (CSR[misa].A == 1'b0))) { + raise (ExceptionCode::IllegalInstruction, mode(), $encoding); + } + + XReg virtual_address = X[xs1]; + X[xd] = amo<8>(virtual_address, X[xs2][7:0], AmoOperation::Minu, 1'b0, 1'b1, $encoding); + + memory_model_release(); + +# SPDX-SnippetBegin +# SPDX-FileCopyrightText: 2017-2025 Contributors to the RISCV Sail Model +# SPDX-License-Identifier: BSD-2-Clause +sail(): | + { + if extension("A") then { + /* Get the address, X(rs1) (no offset). + * Some extensions perform additional checks on address validity. + */ + match ext_data_get_addr(rs1, zeros(), ReadWrite(Data, Data), width) { + Ext_DataAddr_Error(e) => { ext_handle_data_check_error(e); RETIRE_FAIL }, + Ext_DataAddr_OK(vaddr) => { + match translateAddr(vaddr, ReadWrite(Data, Data)) { + TR_Failure(e, _) => { handle_mem_exception(vaddr, e); RETIRE_FAIL }, + TR_Address(addr, _) => { + let eares : MemoryOpResult(unit) = match (width, sizeof(xlen)) { + (BYTE, _) => mem_write_ea(addr, 1, aq & rl, rl, true), + (HALF, _) => mem_write_ea(addr, 2, aq & rl, rl, true), + (WORD, _) => mem_write_ea(addr, 4, aq & rl, rl, true), + (DOUBLE, 64) => mem_write_ea(addr, 8, aq & rl, rl, true), + _ => internal_error(__FILE__, __LINE__, "Unexpected AMO width") + }; + let is_unsigned : bool = match op { + AMOMINU => true, + AMOMAXU => true, + _ => false + }; + let rs2_val : xlenbits = match width { + BYTE => if is_unsigned then zero_extend(X(rs2)[7..0]) else sign_extend(X(rs2)[7..0]), + HALF => if is_unsigned then zero_extend(X(rs2)[15..0]) else sign_extend(X(rs2)[15..0]), + WORD => if is_unsigned then zero_extend(X(rs2)[31..0]) else sign_extend(X(rs2)[31..0]), + DOUBLE => X(rs2) + }; + match (eares) { + MemException(e) => { handle_mem_exception(vaddr, e); RETIRE_FAIL }, + MemValue(_) => { + let mval : MemoryOpResult(xlenbits) = match (width, sizeof(xlen)) { + (BYTE, _) => extend_value(is_unsigned, mem_read(ReadWrite(Data, Data), addr, 1, aq, aq & rl, true)), + (HALF, _) => extend_value(is_unsigned, mem_read(ReadWrite(Data, Data), addr, 2, aq, aq & rl, true)), + (WORD, _) => extend_value(is_unsigned, mem_read(ReadWrite(Data, Data), addr, 4, aq, aq & rl, true)), + (DOUBLE, 64) => extend_value(is_unsigned, mem_read(ReadWrite(Data, Data), addr, 8, aq, aq & rl, true)), + _ => internal_error(__FILE__, __LINE__, "Unexpected AMO width") + }; + match (mval) { + MemException(e) => { handle_mem_exception(vaddr, e); RETIRE_FAIL }, + MemValue(loaded) => { + let result : xlenbits = + match op { + AMOSWAP => rs2_val, + AMOADD => rs2_val + loaded, + AMOXOR => rs2_val ^ loaded, + AMOAND => rs2_val & loaded, + AMOOR => rs2_val | loaded, + + /* These operations convert bitvectors to integer values using [un]signed, + * and back using to_bits(). + */ + AMOMIN => to_bits(sizeof(xlen), min(signed(rs2_val), signed(loaded))), + AMOMAX => to_bits(sizeof(xlen), max(signed(rs2_val), signed(loaded))), + AMOMINU => to_bits(sizeof(xlen), min(unsigned(rs2_val), unsigned(loaded))), + AMOMAXU => to_bits(sizeof(xlen), max(unsigned(rs2_val), unsigned(loaded))) + }; + let rval : xlenbits = match width { + BYTE => sign_extend(loaded[7..0]), + HALF => sign_extend(loaded[15..0]), + WORD => sign_extend(loaded[31..0]), + DOUBLE => loaded + }; + let wval : MemoryOpResult(bool) = match (width, sizeof(xlen)) { + (BYTE, _) => mem_write_value(addr, 1, result[7..0], aq & rl, rl, true), + (HALF, _) => mem_write_value(addr, 2, result[15..0], aq & rl, rl, true), + (WORD, _) => mem_write_value(addr, 4, result[31..0], aq & rl, rl, true), + (DOUBLE, 64) => mem_write_value(addr, 8, result, aq & rl, rl, true), + _ => internal_error(__FILE__, __LINE__, "Unexpected AMO width") + }; + match (wval) { + MemValue(true) => { X(rd) = rval; RETIRE_SUCCESS }, + MemValue(false) => { internal_error(__FILE__, __LINE__, "AMO got false from mem_write_value") }, + MemException(e) => { handle_mem_exception(vaddr, e); RETIRE_FAIL } + } + } + } + } + } + } + } + } + } + } else { + handle_illegal(); + RETIRE_FAIL + } + } + +# SPDX-SnippetEnd diff --git a/spec/std/isa/inst/Zabha/amominu.b.yaml b/spec/std/isa/inst/Zabha/amominu.b.yaml index 003eecb48d..e2317e663a 100644 --- a/spec/std/isa/inst/Zabha/amominu.b.yaml +++ b/spec/std/isa/inst/Zabha/amominu.b.yaml @@ -1,4 +1,6 @@ # Copyright (c) Qualcomm Technologies, Inc. and/or its subsidiaries. + +# WARNING: This file is auto-generated from spec/std/isa/inst/Zaamo/amominu.SIZE.AQRL.layout# Copyright (c) Abhijit Das(Sukuna0007Abhi) # SPDX-License-Identifier: BSD-3-Clause-Clear # yaml-language-server: $schema=../../../../schemas/inst_schema.json @@ -6,18 +8,19 @@ $schema: "inst_schema.json#" kind: instruction name: amominu.b -long_name: No synopsis available +long_name: Atomic MIN unsigned byte description: | - No description available. + Atomically: + + * Load the byte at address _xs1_ + * Write the sign-extended value into _xd_ + * Unsigned compare the least-significant byte of register _xs2_ to the loaded value, and select the minimum value + * Write the minimum to the address in _xs1_ definedBy: Zabha assembly: xd, xs2, (xs1) encoding: - match: 11000------------000-----0101111 + match: 1100000----------000-----0101111 variables: - - name: aq - location: 26-26 - - name: rl - location: 25-25 - name: xs2 location: 24-20 - name: xs1 @@ -29,8 +32,13 @@ access: u: always vs: always vu: always -data_independent_timing: false operation(): | + if (!implemented?(ExtensionName::A) || (MISA_CSR_IMPLEMENTED && (CSR[misa].A == 1'b0))) { + raise (ExceptionCode::IllegalInstruction, mode(), $encoding); + } + + XReg virtual_address = X[xs1]; + X[xd] = amo<8>(virtual_address, X[xs2][7:0], AmoOperation::Minu, 1'b0, 1'b0, $encoding); # SPDX-SnippetBegin # SPDX-FileCopyrightText: 2017-2025 Contributors to the RISCV Sail Model diff --git a/spec/std/isa/inst/Zabha/amominu.h.aq.yaml b/spec/std/isa/inst/Zabha/amominu.h.aq.yaml new file mode 100644 index 0000000000..2ab2a1f525 --- /dev/null +++ b/spec/std/isa/inst/Zabha/amominu.h.aq.yaml @@ -0,0 +1,139 @@ +# Copyright (c) Qualcomm Technologies, Inc. and/or its subsidiaries. + +# WARNING: This file is auto-generated from spec/std/isa/inst/Zaamo/amominu.SIZE.AQRL.layout# Copyright (c) Abhijit Das(Sukuna0007Abhi) +# SPDX-License-Identifier: BSD-3-Clause-Clear + +# yaml-language-server: $schema=../../../../schemas/inst_schema.json + +$schema: "inst_schema.json#" +kind: instruction +name: amominu.h.aq +long_name: Atomic MIN unsigned halfword (acquire) +description: | + Atomically with acquire ordering: + + * Load the halfword at address _xs1_ + * Write the sign-extended value into _xd_ + * Unsigned compare the least-significant halfword of register _xs2_ to the loaded value, and select the minimum value + * Write the minimum to the address in _xs1_ +definedBy: Zabha +assembly: xd, xs2, (xs1) +encoding: + match: 1100010----------001-----0101111 + variables: + - name: xs2 + location: 24-20 + - name: xs1 + location: 19-15 + - name: xd + location: 11-7 +access: + s: always + u: always + vs: always + vu: always +operation(): | + if (!implemented?(ExtensionName::A) || (MISA_CSR_IMPLEMENTED && (CSR[misa].A == 1'b0))) { + raise (ExceptionCode::IllegalInstruction, mode(), $encoding); + } + + memory_model_acquire(); + + XReg virtual_address = X[xs1]; + X[xd] = amo<16>(virtual_address, X[xs2][15:0], AmoOperation::Minu, 1'b1, 1'b0, $encoding); + +# SPDX-SnippetBegin +# SPDX-FileCopyrightText: 2017-2025 Contributors to the RISCV Sail Model +# SPDX-License-Identifier: BSD-2-Clause +sail(): | + { + if extension("A") then { + /* Get the address, X(rs1) (no offset). + * Some extensions perform additional checks on address validity. + */ + match ext_data_get_addr(rs1, zeros(), ReadWrite(Data, Data), width) { + Ext_DataAddr_Error(e) => { ext_handle_data_check_error(e); RETIRE_FAIL }, + Ext_DataAddr_OK(vaddr) => { + match translateAddr(vaddr, ReadWrite(Data, Data)) { + TR_Failure(e, _) => { handle_mem_exception(vaddr, e); RETIRE_FAIL }, + TR_Address(addr, _) => { + let eares : MemoryOpResult(unit) = match (width, sizeof(xlen)) { + (BYTE, _) => mem_write_ea(addr, 1, aq & rl, rl, true), + (HALF, _) => mem_write_ea(addr, 2, aq & rl, rl, true), + (WORD, _) => mem_write_ea(addr, 4, aq & rl, rl, true), + (DOUBLE, 64) => mem_write_ea(addr, 8, aq & rl, rl, true), + _ => internal_error(__FILE__, __LINE__, "Unexpected AMO width") + }; + let is_unsigned : bool = match op { + AMOMINU => true, + AMOMAXU => true, + _ => false + }; + let rs2_val : xlenbits = match width { + BYTE => if is_unsigned then zero_extend(X(rs2)[7..0]) else sign_extend(X(rs2)[7..0]), + HALF => if is_unsigned then zero_extend(X(rs2)[15..0]) else sign_extend(X(rs2)[15..0]), + WORD => if is_unsigned then zero_extend(X(rs2)[31..0]) else sign_extend(X(rs2)[31..0]), + DOUBLE => X(rs2) + }; + match (eares) { + MemException(e) => { handle_mem_exception(vaddr, e); RETIRE_FAIL }, + MemValue(_) => { + let mval : MemoryOpResult(xlenbits) = match (width, sizeof(xlen)) { + (BYTE, _) => extend_value(is_unsigned, mem_read(ReadWrite(Data, Data), addr, 1, aq, aq & rl, true)), + (HALF, _) => extend_value(is_unsigned, mem_read(ReadWrite(Data, Data), addr, 2, aq, aq & rl, true)), + (WORD, _) => extend_value(is_unsigned, mem_read(ReadWrite(Data, Data), addr, 4, aq, aq & rl, true)), + (DOUBLE, 64) => extend_value(is_unsigned, mem_read(ReadWrite(Data, Data), addr, 8, aq, aq & rl, true)), + _ => internal_error(__FILE__, __LINE__, "Unexpected AMO width") + }; + match (mval) { + MemException(e) => { handle_mem_exception(vaddr, e); RETIRE_FAIL }, + MemValue(loaded) => { + let result : xlenbits = + match op { + AMOSWAP => rs2_val, + AMOADD => rs2_val + loaded, + AMOXOR => rs2_val ^ loaded, + AMOAND => rs2_val & loaded, + AMOOR => rs2_val | loaded, + + /* These operations convert bitvectors to integer values using [un]signed, + * and back using to_bits(). + */ + AMOMIN => to_bits(sizeof(xlen), min(signed(rs2_val), signed(loaded))), + AMOMAX => to_bits(sizeof(xlen), max(signed(rs2_val), signed(loaded))), + AMOMINU => to_bits(sizeof(xlen), min(unsigned(rs2_val), unsigned(loaded))), + AMOMAXU => to_bits(sizeof(xlen), max(unsigned(rs2_val), unsigned(loaded))) + }; + let rval : xlenbits = match width { + BYTE => sign_extend(loaded[7..0]), + HALF => sign_extend(loaded[15..0]), + WORD => sign_extend(loaded[31..0]), + DOUBLE => loaded + }; + let wval : MemoryOpResult(bool) = match (width, sizeof(xlen)) { + (BYTE, _) => mem_write_value(addr, 1, result[7..0], aq & rl, rl, true), + (HALF, _) => mem_write_value(addr, 2, result[15..0], aq & rl, rl, true), + (WORD, _) => mem_write_value(addr, 4, result[31..0], aq & rl, rl, true), + (DOUBLE, 64) => mem_write_value(addr, 8, result, aq & rl, rl, true), + _ => internal_error(__FILE__, __LINE__, "Unexpected AMO width") + }; + match (wval) { + MemValue(true) => { X(rd) = rval; RETIRE_SUCCESS }, + MemValue(false) => { internal_error(__FILE__, __LINE__, "AMO got false from mem_write_value") }, + MemException(e) => { handle_mem_exception(vaddr, e); RETIRE_FAIL } + } + } + } + } + } + } + } + } + } + } else { + handle_illegal(); + RETIRE_FAIL + } + } + +# SPDX-SnippetEnd diff --git a/spec/std/isa/inst/Zabha/amominu.h.aqrl.yaml b/spec/std/isa/inst/Zabha/amominu.h.aqrl.yaml new file mode 100644 index 0000000000..26828a0972 --- /dev/null +++ b/spec/std/isa/inst/Zabha/amominu.h.aqrl.yaml @@ -0,0 +1,141 @@ +# Copyright (c) Qualcomm Technologies, Inc. and/or its subsidiaries. + +# WARNING: This file is auto-generated from spec/std/isa/inst/Zaamo/amominu.SIZE.AQRL.layout# Copyright (c) Abhijit Das(Sukuna0007Abhi) +# SPDX-License-Identifier: BSD-3-Clause-Clear + +# yaml-language-server: $schema=../../../../schemas/inst_schema.json + +$schema: "inst_schema.json#" +kind: instruction +name: amominu.h.aqrl +long_name: Atomic MIN unsigned halfword (acquire-release) +description: | + Atomically with acquire and release ordering: + + * Load the halfword at address _xs1_ + * Write the sign-extended value into _xd_ + * Unsigned compare the least-significant halfword of register _xs2_ to the loaded value, and select the minimum value + * Write the minimum to the address in _xs1_ +definedBy: Zabha +assembly: xd, xs2, (xs1) +encoding: + match: 1100011----------001-----0101111 + variables: + - name: xs2 + location: 24-20 + - name: xs1 + location: 19-15 + - name: xd + location: 11-7 +access: + s: always + u: always + vs: always + vu: always +operation(): | + if (!implemented?(ExtensionName::A) || (MISA_CSR_IMPLEMENTED && (CSR[misa].A == 1'b0))) { + raise (ExceptionCode::IllegalInstruction, mode(), $encoding); + } + + memory_model_acquire(); + + XReg virtual_address = X[xs1]; + X[xd] = amo<16>(virtual_address, X[xs2][15:0], AmoOperation::Minu, 1'b1, 1'b1, $encoding); + + memory_model_release(); + +# SPDX-SnippetBegin +# SPDX-FileCopyrightText: 2017-2025 Contributors to the RISCV Sail Model +# SPDX-License-Identifier: BSD-2-Clause +sail(): | + { + if extension("A") then { + /* Get the address, X(rs1) (no offset). + * Some extensions perform additional checks on address validity. + */ + match ext_data_get_addr(rs1, zeros(), ReadWrite(Data, Data), width) { + Ext_DataAddr_Error(e) => { ext_handle_data_check_error(e); RETIRE_FAIL }, + Ext_DataAddr_OK(vaddr) => { + match translateAddr(vaddr, ReadWrite(Data, Data)) { + TR_Failure(e, _) => { handle_mem_exception(vaddr, e); RETIRE_FAIL }, + TR_Address(addr, _) => { + let eares : MemoryOpResult(unit) = match (width, sizeof(xlen)) { + (BYTE, _) => mem_write_ea(addr, 1, aq & rl, rl, true), + (HALF, _) => mem_write_ea(addr, 2, aq & rl, rl, true), + (WORD, _) => mem_write_ea(addr, 4, aq & rl, rl, true), + (DOUBLE, 64) => mem_write_ea(addr, 8, aq & rl, rl, true), + _ => internal_error(__FILE__, __LINE__, "Unexpected AMO width") + }; + let is_unsigned : bool = match op { + AMOMINU => true, + AMOMAXU => true, + _ => false + }; + let rs2_val : xlenbits = match width { + BYTE => if is_unsigned then zero_extend(X(rs2)[7..0]) else sign_extend(X(rs2)[7..0]), + HALF => if is_unsigned then zero_extend(X(rs2)[15..0]) else sign_extend(X(rs2)[15..0]), + WORD => if is_unsigned then zero_extend(X(rs2)[31..0]) else sign_extend(X(rs2)[31..0]), + DOUBLE => X(rs2) + }; + match (eares) { + MemException(e) => { handle_mem_exception(vaddr, e); RETIRE_FAIL }, + MemValue(_) => { + let mval : MemoryOpResult(xlenbits) = match (width, sizeof(xlen)) { + (BYTE, _) => extend_value(is_unsigned, mem_read(ReadWrite(Data, Data), addr, 1, aq, aq & rl, true)), + (HALF, _) => extend_value(is_unsigned, mem_read(ReadWrite(Data, Data), addr, 2, aq, aq & rl, true)), + (WORD, _) => extend_value(is_unsigned, mem_read(ReadWrite(Data, Data), addr, 4, aq, aq & rl, true)), + (DOUBLE, 64) => extend_value(is_unsigned, mem_read(ReadWrite(Data, Data), addr, 8, aq, aq & rl, true)), + _ => internal_error(__FILE__, __LINE__, "Unexpected AMO width") + }; + match (mval) { + MemException(e) => { handle_mem_exception(vaddr, e); RETIRE_FAIL }, + MemValue(loaded) => { + let result : xlenbits = + match op { + AMOSWAP => rs2_val, + AMOADD => rs2_val + loaded, + AMOXOR => rs2_val ^ loaded, + AMOAND => rs2_val & loaded, + AMOOR => rs2_val | loaded, + + /* These operations convert bitvectors to integer values using [un]signed, + * and back using to_bits(). + */ + AMOMIN => to_bits(sizeof(xlen), min(signed(rs2_val), signed(loaded))), + AMOMAX => to_bits(sizeof(xlen), max(signed(rs2_val), signed(loaded))), + AMOMINU => to_bits(sizeof(xlen), min(unsigned(rs2_val), unsigned(loaded))), + AMOMAXU => to_bits(sizeof(xlen), max(unsigned(rs2_val), unsigned(loaded))) + }; + let rval : xlenbits = match width { + BYTE => sign_extend(loaded[7..0]), + HALF => sign_extend(loaded[15..0]), + WORD => sign_extend(loaded[31..0]), + DOUBLE => loaded + }; + let wval : MemoryOpResult(bool) = match (width, sizeof(xlen)) { + (BYTE, _) => mem_write_value(addr, 1, result[7..0], aq & rl, rl, true), + (HALF, _) => mem_write_value(addr, 2, result[15..0], aq & rl, rl, true), + (WORD, _) => mem_write_value(addr, 4, result[31..0], aq & rl, rl, true), + (DOUBLE, 64) => mem_write_value(addr, 8, result, aq & rl, rl, true), + _ => internal_error(__FILE__, __LINE__, "Unexpected AMO width") + }; + match (wval) { + MemValue(true) => { X(rd) = rval; RETIRE_SUCCESS }, + MemValue(false) => { internal_error(__FILE__, __LINE__, "AMO got false from mem_write_value") }, + MemException(e) => { handle_mem_exception(vaddr, e); RETIRE_FAIL } + } + } + } + } + } + } + } + } + } + } else { + handle_illegal(); + RETIRE_FAIL + } + } + +# SPDX-SnippetEnd diff --git a/spec/std/isa/inst/Zabha/amominu.h.rl.yaml b/spec/std/isa/inst/Zabha/amominu.h.rl.yaml new file mode 100644 index 0000000000..0d617e9754 --- /dev/null +++ b/spec/std/isa/inst/Zabha/amominu.h.rl.yaml @@ -0,0 +1,139 @@ +# Copyright (c) Qualcomm Technologies, Inc. and/or its subsidiaries. + +# WARNING: This file is auto-generated from spec/std/isa/inst/Zaamo/amominu.SIZE.AQRL.layout# Copyright (c) Abhijit Das(Sukuna0007Abhi) +# SPDX-License-Identifier: BSD-3-Clause-Clear + +# yaml-language-server: $schema=../../../../schemas/inst_schema.json + +$schema: "inst_schema.json#" +kind: instruction +name: amominu.h.rl +long_name: Atomic MIN unsigned halfword (release) +description: | + Atomically with release ordering: + + * Load the halfword at address _xs1_ + * Write the sign-extended value into _xd_ + * Unsigned compare the least-significant halfword of register _xs2_ to the loaded value, and select the minimum value + * Write the minimum to the address in _xs1_ +definedBy: Zabha +assembly: xd, xs2, (xs1) +encoding: + match: 1100001----------001-----0101111 + variables: + - name: xs2 + location: 24-20 + - name: xs1 + location: 19-15 + - name: xd + location: 11-7 +access: + s: always + u: always + vs: always + vu: always +operation(): | + if (!implemented?(ExtensionName::A) || (MISA_CSR_IMPLEMENTED && (CSR[misa].A == 1'b0))) { + raise (ExceptionCode::IllegalInstruction, mode(), $encoding); + } + + XReg virtual_address = X[xs1]; + X[xd] = amo<16>(virtual_address, X[xs2][15:0], AmoOperation::Minu, 1'b0, 1'b1, $encoding); + + memory_model_release(); + +# SPDX-SnippetBegin +# SPDX-FileCopyrightText: 2017-2025 Contributors to the RISCV Sail Model +# SPDX-License-Identifier: BSD-2-Clause +sail(): | + { + if extension("A") then { + /* Get the address, X(rs1) (no offset). + * Some extensions perform additional checks on address validity. + */ + match ext_data_get_addr(rs1, zeros(), ReadWrite(Data, Data), width) { + Ext_DataAddr_Error(e) => { ext_handle_data_check_error(e); RETIRE_FAIL }, + Ext_DataAddr_OK(vaddr) => { + match translateAddr(vaddr, ReadWrite(Data, Data)) { + TR_Failure(e, _) => { handle_mem_exception(vaddr, e); RETIRE_FAIL }, + TR_Address(addr, _) => { + let eares : MemoryOpResult(unit) = match (width, sizeof(xlen)) { + (BYTE, _) => mem_write_ea(addr, 1, aq & rl, rl, true), + (HALF, _) => mem_write_ea(addr, 2, aq & rl, rl, true), + (WORD, _) => mem_write_ea(addr, 4, aq & rl, rl, true), + (DOUBLE, 64) => mem_write_ea(addr, 8, aq & rl, rl, true), + _ => internal_error(__FILE__, __LINE__, "Unexpected AMO width") + }; + let is_unsigned : bool = match op { + AMOMINU => true, + AMOMAXU => true, + _ => false + }; + let rs2_val : xlenbits = match width { + BYTE => if is_unsigned then zero_extend(X(rs2)[7..0]) else sign_extend(X(rs2)[7..0]), + HALF => if is_unsigned then zero_extend(X(rs2)[15..0]) else sign_extend(X(rs2)[15..0]), + WORD => if is_unsigned then zero_extend(X(rs2)[31..0]) else sign_extend(X(rs2)[31..0]), + DOUBLE => X(rs2) + }; + match (eares) { + MemException(e) => { handle_mem_exception(vaddr, e); RETIRE_FAIL }, + MemValue(_) => { + let mval : MemoryOpResult(xlenbits) = match (width, sizeof(xlen)) { + (BYTE, _) => extend_value(is_unsigned, mem_read(ReadWrite(Data, Data), addr, 1, aq, aq & rl, true)), + (HALF, _) => extend_value(is_unsigned, mem_read(ReadWrite(Data, Data), addr, 2, aq, aq & rl, true)), + (WORD, _) => extend_value(is_unsigned, mem_read(ReadWrite(Data, Data), addr, 4, aq, aq & rl, true)), + (DOUBLE, 64) => extend_value(is_unsigned, mem_read(ReadWrite(Data, Data), addr, 8, aq, aq & rl, true)), + _ => internal_error(__FILE__, __LINE__, "Unexpected AMO width") + }; + match (mval) { + MemException(e) => { handle_mem_exception(vaddr, e); RETIRE_FAIL }, + MemValue(loaded) => { + let result : xlenbits = + match op { + AMOSWAP => rs2_val, + AMOADD => rs2_val + loaded, + AMOXOR => rs2_val ^ loaded, + AMOAND => rs2_val & loaded, + AMOOR => rs2_val | loaded, + + /* These operations convert bitvectors to integer values using [un]signed, + * and back using to_bits(). + */ + AMOMIN => to_bits(sizeof(xlen), min(signed(rs2_val), signed(loaded))), + AMOMAX => to_bits(sizeof(xlen), max(signed(rs2_val), signed(loaded))), + AMOMINU => to_bits(sizeof(xlen), min(unsigned(rs2_val), unsigned(loaded))), + AMOMAXU => to_bits(sizeof(xlen), max(unsigned(rs2_val), unsigned(loaded))) + }; + let rval : xlenbits = match width { + BYTE => sign_extend(loaded[7..0]), + HALF => sign_extend(loaded[15..0]), + WORD => sign_extend(loaded[31..0]), + DOUBLE => loaded + }; + let wval : MemoryOpResult(bool) = match (width, sizeof(xlen)) { + (BYTE, _) => mem_write_value(addr, 1, result[7..0], aq & rl, rl, true), + (HALF, _) => mem_write_value(addr, 2, result[15..0], aq & rl, rl, true), + (WORD, _) => mem_write_value(addr, 4, result[31..0], aq & rl, rl, true), + (DOUBLE, 64) => mem_write_value(addr, 8, result, aq & rl, rl, true), + _ => internal_error(__FILE__, __LINE__, "Unexpected AMO width") + }; + match (wval) { + MemValue(true) => { X(rd) = rval; RETIRE_SUCCESS }, + MemValue(false) => { internal_error(__FILE__, __LINE__, "AMO got false from mem_write_value") }, + MemException(e) => { handle_mem_exception(vaddr, e); RETIRE_FAIL } + } + } + } + } + } + } + } + } + } + } else { + handle_illegal(); + RETIRE_FAIL + } + } + +# SPDX-SnippetEnd diff --git a/spec/std/isa/inst/Zabha/amominu.h.yaml b/spec/std/isa/inst/Zabha/amominu.h.yaml index 4188264011..2fb37d0fbc 100644 --- a/spec/std/isa/inst/Zabha/amominu.h.yaml +++ b/spec/std/isa/inst/Zabha/amominu.h.yaml @@ -1,4 +1,6 @@ # Copyright (c) Qualcomm Technologies, Inc. and/or its subsidiaries. + +# WARNING: This file is auto-generated from spec/std/isa/inst/Zaamo/amominu.SIZE.AQRL.layout# Copyright (c) Abhijit Das(Sukuna0007Abhi) # SPDX-License-Identifier: BSD-3-Clause-Clear # yaml-language-server: $schema=../../../../schemas/inst_schema.json @@ -6,18 +8,19 @@ $schema: "inst_schema.json#" kind: instruction name: amominu.h -long_name: No synopsis available +long_name: Atomic MIN unsigned halfword description: | - No description available. + Atomically: + + * Load the halfword at address _xs1_ + * Write the sign-extended value into _xd_ + * Unsigned compare the least-significant halfword of register _xs2_ to the loaded value, and select the minimum value + * Write the minimum to the address in _xs1_ definedBy: Zabha assembly: xd, xs2, (xs1) encoding: - match: 11000------------001-----0101111 + match: 1100000----------001-----0101111 variables: - - name: aq - location: 26-26 - - name: rl - location: 25-25 - name: xs2 location: 24-20 - name: xs1 @@ -29,8 +32,13 @@ access: u: always vs: always vu: always -data_independent_timing: false operation(): | + if (!implemented?(ExtensionName::A) || (MISA_CSR_IMPLEMENTED && (CSR[misa].A == 1'b0))) { + raise (ExceptionCode::IllegalInstruction, mode(), $encoding); + } + + XReg virtual_address = X[xs1]; + X[xd] = amo<16>(virtual_address, X[xs2][15:0], AmoOperation::Minu, 1'b0, 1'b0, $encoding); # SPDX-SnippetBegin # SPDX-FileCopyrightText: 2017-2025 Contributors to the RISCV Sail Model diff --git a/spec/std/isa/inst/Zabha/amoor.b.aq.yaml b/spec/std/isa/inst/Zabha/amoor.b.aq.yaml new file mode 100644 index 0000000000..eeac6fcd5a --- /dev/null +++ b/spec/std/isa/inst/Zabha/amoor.b.aq.yaml @@ -0,0 +1,139 @@ +# Copyright (c) Qualcomm Technologies, Inc. and/or its subsidiaries. + +# WARNING: This file is auto-generated from spec/std/isa/inst/Zaamo/amoor.SIZE.AQRL.layout# Copyright (c) Abhijit Das(Sukuna0007Abhi) +# SPDX-License-Identifier: BSD-3-Clause-Clear + +# yaml-language-server: $schema=../../../../schemas/inst_schema.json + +$schema: "inst_schema.json#" +kind: instruction +name: amoor.b.aq +long_name: Atomic fetch-and-or byte (acquire) +description: | + Atomically with acquire ordering: + + * Load the byte at address _xs1_ + * Write the sign-extended value into _xd_ + * OR the least-significant byte of register _xs2_ to the loaded value + * Write the result to the address in _xs1_ +definedBy: Zabha +assembly: xd, xs2, (xs1) +encoding: + match: 0100010----------000-----0101111 + variables: + - name: xs2 + location: 24-20 + - name: xs1 + location: 19-15 + - name: xd + location: 11-7 +access: + s: always + u: always + vs: always + vu: always +operation(): | + if (!implemented?(ExtensionName::A) || (MISA_CSR_IMPLEMENTED && (CSR[misa].A == 1'b0))) { + raise (ExceptionCode::IllegalInstruction, mode(), $encoding); + } + + memory_model_acquire(); + + XReg virtual_address = X[xs1]; + X[xd] = amo<8>(virtual_address, X[xs2][7:0], AmoOperation::Or, 1'b1, 1'b0, $encoding); + +# SPDX-SnippetBegin +# SPDX-FileCopyrightText: 2017-2025 Contributors to the RISCV Sail Model +# SPDX-License-Identifier: BSD-2-Clause +sail(): | + { + if extension("A") then { + /* Get the address, X(rs1) (no offset). + * Some extensions perform additional checks on address validity. + */ + match ext_data_get_addr(rs1, zeros(), ReadWrite(Data, Data), width) { + Ext_DataAddr_Error(e) => { ext_handle_data_check_error(e); RETIRE_FAIL }, + Ext_DataAddr_OK(vaddr) => { + match translateAddr(vaddr, ReadWrite(Data, Data)) { + TR_Failure(e, _) => { handle_mem_exception(vaddr, e); RETIRE_FAIL }, + TR_Address(addr, _) => { + let eares : MemoryOpResult(unit) = match (width, sizeof(xlen)) { + (BYTE, _) => mem_write_ea(addr, 1, aq & rl, rl, true), + (HALF, _) => mem_write_ea(addr, 2, aq & rl, rl, true), + (WORD, _) => mem_write_ea(addr, 4, aq & rl, rl, true), + (DOUBLE, 64) => mem_write_ea(addr, 8, aq & rl, rl, true), + _ => internal_error(__FILE__, __LINE__, "Unexpected AMO width") + }; + let is_unsigned : bool = match op { + AMOMINU => true, + AMOMAXU => true, + _ => false + }; + let rs2_val : xlenbits = match width { + BYTE => if is_unsigned then zero_extend(X(rs2)[7..0]) else sign_extend(X(rs2)[7..0]), + HALF => if is_unsigned then zero_extend(X(rs2)[15..0]) else sign_extend(X(rs2)[15..0]), + WORD => if is_unsigned then zero_extend(X(rs2)[31..0]) else sign_extend(X(rs2)[31..0]), + DOUBLE => X(rs2) + }; + match (eares) { + MemException(e) => { handle_mem_exception(vaddr, e); RETIRE_FAIL }, + MemValue(_) => { + let mval : MemoryOpResult(xlenbits) = match (width, sizeof(xlen)) { + (BYTE, _) => extend_value(is_unsigned, mem_read(ReadWrite(Data, Data), addr, 1, aq, aq & rl, true)), + (HALF, _) => extend_value(is_unsigned, mem_read(ReadWrite(Data, Data), addr, 2, aq, aq & rl, true)), + (WORD, _) => extend_value(is_unsigned, mem_read(ReadWrite(Data, Data), addr, 4, aq, aq & rl, true)), + (DOUBLE, 64) => extend_value(is_unsigned, mem_read(ReadWrite(Data, Data), addr, 8, aq, aq & rl, true)), + _ => internal_error(__FILE__, __LINE__, "Unexpected AMO width") + }; + match (mval) { + MemException(e) => { handle_mem_exception(vaddr, e); RETIRE_FAIL }, + MemValue(loaded) => { + let result : xlenbits = + match op { + AMOSWAP => rs2_val, + AMOADD => rs2_val + loaded, + AMOXOR => rs2_val ^ loaded, + AMOAND => rs2_val & loaded, + AMOOR => rs2_val | loaded, + + /* These operations convert bitvectors to integer values using [un]signed, + * and back using to_bits(). + */ + AMOMIN => to_bits(sizeof(xlen), min(signed(rs2_val), signed(loaded))), + AMOMAX => to_bits(sizeof(xlen), max(signed(rs2_val), signed(loaded))), + AMOMINU => to_bits(sizeof(xlen), min(unsigned(rs2_val), unsigned(loaded))), + AMOMAXU => to_bits(sizeof(xlen), max(unsigned(rs2_val), unsigned(loaded))) + }; + let rval : xlenbits = match width { + BYTE => sign_extend(loaded[7..0]), + HALF => sign_extend(loaded[15..0]), + WORD => sign_extend(loaded[31..0]), + DOUBLE => loaded + }; + let wval : MemoryOpResult(bool) = match (width, sizeof(xlen)) { + (BYTE, _) => mem_write_value(addr, 1, result[7..0], aq & rl, rl, true), + (HALF, _) => mem_write_value(addr, 2, result[15..0], aq & rl, rl, true), + (WORD, _) => mem_write_value(addr, 4, result[31..0], aq & rl, rl, true), + (DOUBLE, 64) => mem_write_value(addr, 8, result, aq & rl, rl, true), + _ => internal_error(__FILE__, __LINE__, "Unexpected AMO width") + }; + match (wval) { + MemValue(true) => { X(rd) = rval; RETIRE_SUCCESS }, + MemValue(false) => { internal_error(__FILE__, __LINE__, "AMO got false from mem_write_value") }, + MemException(e) => { handle_mem_exception(vaddr, e); RETIRE_FAIL } + } + } + } + } + } + } + } + } + } + } else { + handle_illegal(); + RETIRE_FAIL + } + } + +# SPDX-SnippetEnd diff --git a/spec/std/isa/inst/Zabha/amoor.b.aqrl.yaml b/spec/std/isa/inst/Zabha/amoor.b.aqrl.yaml new file mode 100644 index 0000000000..6d301c020c --- /dev/null +++ b/spec/std/isa/inst/Zabha/amoor.b.aqrl.yaml @@ -0,0 +1,141 @@ +# Copyright (c) Qualcomm Technologies, Inc. and/or its subsidiaries. + +# WARNING: This file is auto-generated from spec/std/isa/inst/Zaamo/amoor.SIZE.AQRL.layout# Copyright (c) Abhijit Das(Sukuna0007Abhi) +# SPDX-License-Identifier: BSD-3-Clause-Clear + +# yaml-language-server: $schema=../../../../schemas/inst_schema.json + +$schema: "inst_schema.json#" +kind: instruction +name: amoor.b.aqrl +long_name: Atomic fetch-and-or byte (acquire-release) +description: | + Atomically with acquire and release ordering: + + * Load the byte at address _xs1_ + * Write the sign-extended value into _xd_ + * OR the least-significant byte of register _xs2_ to the loaded value + * Write the result to the address in _xs1_ +definedBy: Zabha +assembly: xd, xs2, (xs1) +encoding: + match: 0100011----------000-----0101111 + variables: + - name: xs2 + location: 24-20 + - name: xs1 + location: 19-15 + - name: xd + location: 11-7 +access: + s: always + u: always + vs: always + vu: always +operation(): | + if (!implemented?(ExtensionName::A) || (MISA_CSR_IMPLEMENTED && (CSR[misa].A == 1'b0))) { + raise (ExceptionCode::IllegalInstruction, mode(), $encoding); + } + + memory_model_acquire(); + + XReg virtual_address = X[xs1]; + X[xd] = amo<8>(virtual_address, X[xs2][7:0], AmoOperation::Or, 1'b1, 1'b1, $encoding); + + memory_model_release(); + +# SPDX-SnippetBegin +# SPDX-FileCopyrightText: 2017-2025 Contributors to the RISCV Sail Model +# SPDX-License-Identifier: BSD-2-Clause +sail(): | + { + if extension("A") then { + /* Get the address, X(rs1) (no offset). + * Some extensions perform additional checks on address validity. + */ + match ext_data_get_addr(rs1, zeros(), ReadWrite(Data, Data), width) { + Ext_DataAddr_Error(e) => { ext_handle_data_check_error(e); RETIRE_FAIL }, + Ext_DataAddr_OK(vaddr) => { + match translateAddr(vaddr, ReadWrite(Data, Data)) { + TR_Failure(e, _) => { handle_mem_exception(vaddr, e); RETIRE_FAIL }, + TR_Address(addr, _) => { + let eares : MemoryOpResult(unit) = match (width, sizeof(xlen)) { + (BYTE, _) => mem_write_ea(addr, 1, aq & rl, rl, true), + (HALF, _) => mem_write_ea(addr, 2, aq & rl, rl, true), + (WORD, _) => mem_write_ea(addr, 4, aq & rl, rl, true), + (DOUBLE, 64) => mem_write_ea(addr, 8, aq & rl, rl, true), + _ => internal_error(__FILE__, __LINE__, "Unexpected AMO width") + }; + let is_unsigned : bool = match op { + AMOMINU => true, + AMOMAXU => true, + _ => false + }; + let rs2_val : xlenbits = match width { + BYTE => if is_unsigned then zero_extend(X(rs2)[7..0]) else sign_extend(X(rs2)[7..0]), + HALF => if is_unsigned then zero_extend(X(rs2)[15..0]) else sign_extend(X(rs2)[15..0]), + WORD => if is_unsigned then zero_extend(X(rs2)[31..0]) else sign_extend(X(rs2)[31..0]), + DOUBLE => X(rs2) + }; + match (eares) { + MemException(e) => { handle_mem_exception(vaddr, e); RETIRE_FAIL }, + MemValue(_) => { + let mval : MemoryOpResult(xlenbits) = match (width, sizeof(xlen)) { + (BYTE, _) => extend_value(is_unsigned, mem_read(ReadWrite(Data, Data), addr, 1, aq, aq & rl, true)), + (HALF, _) => extend_value(is_unsigned, mem_read(ReadWrite(Data, Data), addr, 2, aq, aq & rl, true)), + (WORD, _) => extend_value(is_unsigned, mem_read(ReadWrite(Data, Data), addr, 4, aq, aq & rl, true)), + (DOUBLE, 64) => extend_value(is_unsigned, mem_read(ReadWrite(Data, Data), addr, 8, aq, aq & rl, true)), + _ => internal_error(__FILE__, __LINE__, "Unexpected AMO width") + }; + match (mval) { + MemException(e) => { handle_mem_exception(vaddr, e); RETIRE_FAIL }, + MemValue(loaded) => { + let result : xlenbits = + match op { + AMOSWAP => rs2_val, + AMOADD => rs2_val + loaded, + AMOXOR => rs2_val ^ loaded, + AMOAND => rs2_val & loaded, + AMOOR => rs2_val | loaded, + + /* These operations convert bitvectors to integer values using [un]signed, + * and back using to_bits(). + */ + AMOMIN => to_bits(sizeof(xlen), min(signed(rs2_val), signed(loaded))), + AMOMAX => to_bits(sizeof(xlen), max(signed(rs2_val), signed(loaded))), + AMOMINU => to_bits(sizeof(xlen), min(unsigned(rs2_val), unsigned(loaded))), + AMOMAXU => to_bits(sizeof(xlen), max(unsigned(rs2_val), unsigned(loaded))) + }; + let rval : xlenbits = match width { + BYTE => sign_extend(loaded[7..0]), + HALF => sign_extend(loaded[15..0]), + WORD => sign_extend(loaded[31..0]), + DOUBLE => loaded + }; + let wval : MemoryOpResult(bool) = match (width, sizeof(xlen)) { + (BYTE, _) => mem_write_value(addr, 1, result[7..0], aq & rl, rl, true), + (HALF, _) => mem_write_value(addr, 2, result[15..0], aq & rl, rl, true), + (WORD, _) => mem_write_value(addr, 4, result[31..0], aq & rl, rl, true), + (DOUBLE, 64) => mem_write_value(addr, 8, result, aq & rl, rl, true), + _ => internal_error(__FILE__, __LINE__, "Unexpected AMO width") + }; + match (wval) { + MemValue(true) => { X(rd) = rval; RETIRE_SUCCESS }, + MemValue(false) => { internal_error(__FILE__, __LINE__, "AMO got false from mem_write_value") }, + MemException(e) => { handle_mem_exception(vaddr, e); RETIRE_FAIL } + } + } + } + } + } + } + } + } + } + } else { + handle_illegal(); + RETIRE_FAIL + } + } + +# SPDX-SnippetEnd diff --git a/spec/std/isa/inst/Zabha/amoor.b.rl.yaml b/spec/std/isa/inst/Zabha/amoor.b.rl.yaml new file mode 100644 index 0000000000..4f52fa87e6 --- /dev/null +++ b/spec/std/isa/inst/Zabha/amoor.b.rl.yaml @@ -0,0 +1,139 @@ +# Copyright (c) Qualcomm Technologies, Inc. and/or its subsidiaries. + +# WARNING: This file is auto-generated from spec/std/isa/inst/Zaamo/amoor.SIZE.AQRL.layout# Copyright (c) Abhijit Das(Sukuna0007Abhi) +# SPDX-License-Identifier: BSD-3-Clause-Clear + +# yaml-language-server: $schema=../../../../schemas/inst_schema.json + +$schema: "inst_schema.json#" +kind: instruction +name: amoor.b.rl +long_name: Atomic fetch-and-or byte (release) +description: | + Atomically with release ordering: + + * Load the byte at address _xs1_ + * Write the sign-extended value into _xd_ + * OR the least-significant byte of register _xs2_ to the loaded value + * Write the result to the address in _xs1_ +definedBy: Zabha +assembly: xd, xs2, (xs1) +encoding: + match: 0100001----------000-----0101111 + variables: + - name: xs2 + location: 24-20 + - name: xs1 + location: 19-15 + - name: xd + location: 11-7 +access: + s: always + u: always + vs: always + vu: always +operation(): | + if (!implemented?(ExtensionName::A) || (MISA_CSR_IMPLEMENTED && (CSR[misa].A == 1'b0))) { + raise (ExceptionCode::IllegalInstruction, mode(), $encoding); + } + + XReg virtual_address = X[xs1]; + X[xd] = amo<8>(virtual_address, X[xs2][7:0], AmoOperation::Or, 1'b0, 1'b1, $encoding); + + memory_model_release(); + +# SPDX-SnippetBegin +# SPDX-FileCopyrightText: 2017-2025 Contributors to the RISCV Sail Model +# SPDX-License-Identifier: BSD-2-Clause +sail(): | + { + if extension("A") then { + /* Get the address, X(rs1) (no offset). + * Some extensions perform additional checks on address validity. + */ + match ext_data_get_addr(rs1, zeros(), ReadWrite(Data, Data), width) { + Ext_DataAddr_Error(e) => { ext_handle_data_check_error(e); RETIRE_FAIL }, + Ext_DataAddr_OK(vaddr) => { + match translateAddr(vaddr, ReadWrite(Data, Data)) { + TR_Failure(e, _) => { handle_mem_exception(vaddr, e); RETIRE_FAIL }, + TR_Address(addr, _) => { + let eares : MemoryOpResult(unit) = match (width, sizeof(xlen)) { + (BYTE, _) => mem_write_ea(addr, 1, aq & rl, rl, true), + (HALF, _) => mem_write_ea(addr, 2, aq & rl, rl, true), + (WORD, _) => mem_write_ea(addr, 4, aq & rl, rl, true), + (DOUBLE, 64) => mem_write_ea(addr, 8, aq & rl, rl, true), + _ => internal_error(__FILE__, __LINE__, "Unexpected AMO width") + }; + let is_unsigned : bool = match op { + AMOMINU => true, + AMOMAXU => true, + _ => false + }; + let rs2_val : xlenbits = match width { + BYTE => if is_unsigned then zero_extend(X(rs2)[7..0]) else sign_extend(X(rs2)[7..0]), + HALF => if is_unsigned then zero_extend(X(rs2)[15..0]) else sign_extend(X(rs2)[15..0]), + WORD => if is_unsigned then zero_extend(X(rs2)[31..0]) else sign_extend(X(rs2)[31..0]), + DOUBLE => X(rs2) + }; + match (eares) { + MemException(e) => { handle_mem_exception(vaddr, e); RETIRE_FAIL }, + MemValue(_) => { + let mval : MemoryOpResult(xlenbits) = match (width, sizeof(xlen)) { + (BYTE, _) => extend_value(is_unsigned, mem_read(ReadWrite(Data, Data), addr, 1, aq, aq & rl, true)), + (HALF, _) => extend_value(is_unsigned, mem_read(ReadWrite(Data, Data), addr, 2, aq, aq & rl, true)), + (WORD, _) => extend_value(is_unsigned, mem_read(ReadWrite(Data, Data), addr, 4, aq, aq & rl, true)), + (DOUBLE, 64) => extend_value(is_unsigned, mem_read(ReadWrite(Data, Data), addr, 8, aq, aq & rl, true)), + _ => internal_error(__FILE__, __LINE__, "Unexpected AMO width") + }; + match (mval) { + MemException(e) => { handle_mem_exception(vaddr, e); RETIRE_FAIL }, + MemValue(loaded) => { + let result : xlenbits = + match op { + AMOSWAP => rs2_val, + AMOADD => rs2_val + loaded, + AMOXOR => rs2_val ^ loaded, + AMOAND => rs2_val & loaded, + AMOOR => rs2_val | loaded, + + /* These operations convert bitvectors to integer values using [un]signed, + * and back using to_bits(). + */ + AMOMIN => to_bits(sizeof(xlen), min(signed(rs2_val), signed(loaded))), + AMOMAX => to_bits(sizeof(xlen), max(signed(rs2_val), signed(loaded))), + AMOMINU => to_bits(sizeof(xlen), min(unsigned(rs2_val), unsigned(loaded))), + AMOMAXU => to_bits(sizeof(xlen), max(unsigned(rs2_val), unsigned(loaded))) + }; + let rval : xlenbits = match width { + BYTE => sign_extend(loaded[7..0]), + HALF => sign_extend(loaded[15..0]), + WORD => sign_extend(loaded[31..0]), + DOUBLE => loaded + }; + let wval : MemoryOpResult(bool) = match (width, sizeof(xlen)) { + (BYTE, _) => mem_write_value(addr, 1, result[7..0], aq & rl, rl, true), + (HALF, _) => mem_write_value(addr, 2, result[15..0], aq & rl, rl, true), + (WORD, _) => mem_write_value(addr, 4, result[31..0], aq & rl, rl, true), + (DOUBLE, 64) => mem_write_value(addr, 8, result, aq & rl, rl, true), + _ => internal_error(__FILE__, __LINE__, "Unexpected AMO width") + }; + match (wval) { + MemValue(true) => { X(rd) = rval; RETIRE_SUCCESS }, + MemValue(false) => { internal_error(__FILE__, __LINE__, "AMO got false from mem_write_value") }, + MemException(e) => { handle_mem_exception(vaddr, e); RETIRE_FAIL } + } + } + } + } + } + } + } + } + } + } else { + handle_illegal(); + RETIRE_FAIL + } + } + +# SPDX-SnippetEnd diff --git a/spec/std/isa/inst/Zabha/amoor.b.yaml b/spec/std/isa/inst/Zabha/amoor.b.yaml index 7cff5293ea..031841ff34 100644 --- a/spec/std/isa/inst/Zabha/amoor.b.yaml +++ b/spec/std/isa/inst/Zabha/amoor.b.yaml @@ -1,4 +1,6 @@ # Copyright (c) Qualcomm Technologies, Inc. and/or its subsidiaries. + +# WARNING: This file is auto-generated from spec/std/isa/inst/Zaamo/amoor.SIZE.AQRL.layout# Copyright (c) Abhijit Das(Sukuna0007Abhi) # SPDX-License-Identifier: BSD-3-Clause-Clear # yaml-language-server: $schema=../../../../schemas/inst_schema.json @@ -6,18 +8,19 @@ $schema: "inst_schema.json#" kind: instruction name: amoor.b -long_name: No synopsis available +long_name: Atomic fetch-and-or byte description: | - No description available. + Atomically: + + * Load the byte at address _xs1_ + * Write the sign-extended value into _xd_ + * OR the least-significant byte of register _xs2_ to the loaded value + * Write the result to the address in _xs1_ definedBy: Zabha assembly: xd, xs2, (xs1) encoding: - match: 01000------------000-----0101111 + match: 0100000----------000-----0101111 variables: - - name: aq - location: 26-26 - - name: rl - location: 25-25 - name: xs2 location: 24-20 - name: xs1 @@ -29,8 +32,13 @@ access: u: always vs: always vu: always -data_independent_timing: false operation(): | + if (!implemented?(ExtensionName::A) || (MISA_CSR_IMPLEMENTED && (CSR[misa].A == 1'b0))) { + raise (ExceptionCode::IllegalInstruction, mode(), $encoding); + } + + XReg virtual_address = X[xs1]; + X[xd] = amo<8>(virtual_address, X[xs2][7:0], AmoOperation::Or, 1'b0, 1'b0, $encoding); # SPDX-SnippetBegin # SPDX-FileCopyrightText: 2017-2025 Contributors to the RISCV Sail Model diff --git a/spec/std/isa/inst/Zabha/amoor.h.aq.yaml b/spec/std/isa/inst/Zabha/amoor.h.aq.yaml new file mode 100644 index 0000000000..86317b690f --- /dev/null +++ b/spec/std/isa/inst/Zabha/amoor.h.aq.yaml @@ -0,0 +1,139 @@ +# Copyright (c) Qualcomm Technologies, Inc. and/or its subsidiaries. + +# WARNING: This file is auto-generated from spec/std/isa/inst/Zaamo/amoor.SIZE.AQRL.layout# Copyright (c) Abhijit Das(Sukuna0007Abhi) +# SPDX-License-Identifier: BSD-3-Clause-Clear + +# yaml-language-server: $schema=../../../../schemas/inst_schema.json + +$schema: "inst_schema.json#" +kind: instruction +name: amoor.h.aq +long_name: Atomic fetch-and-or halfword (acquire) +description: | + Atomically with acquire ordering: + + * Load the halfword at address _xs1_ + * Write the sign-extended value into _xd_ + * OR the least-significant halfword of register _xs2_ to the loaded value + * Write the result to the address in _xs1_ +definedBy: Zabha +assembly: xd, xs2, (xs1) +encoding: + match: 0100010----------001-----0101111 + variables: + - name: xs2 + location: 24-20 + - name: xs1 + location: 19-15 + - name: xd + location: 11-7 +access: + s: always + u: always + vs: always + vu: always +operation(): | + if (!implemented?(ExtensionName::A) || (MISA_CSR_IMPLEMENTED && (CSR[misa].A == 1'b0))) { + raise (ExceptionCode::IllegalInstruction, mode(), $encoding); + } + + memory_model_acquire(); + + XReg virtual_address = X[xs1]; + X[xd] = amo<16>(virtual_address, X[xs2][15:0], AmoOperation::Or, 1'b1, 1'b0, $encoding); + +# SPDX-SnippetBegin +# SPDX-FileCopyrightText: 2017-2025 Contributors to the RISCV Sail Model +# SPDX-License-Identifier: BSD-2-Clause +sail(): | + { + if extension("A") then { + /* Get the address, X(rs1) (no offset). + * Some extensions perform additional checks on address validity. + */ + match ext_data_get_addr(rs1, zeros(), ReadWrite(Data, Data), width) { + Ext_DataAddr_Error(e) => { ext_handle_data_check_error(e); RETIRE_FAIL }, + Ext_DataAddr_OK(vaddr) => { + match translateAddr(vaddr, ReadWrite(Data, Data)) { + TR_Failure(e, _) => { handle_mem_exception(vaddr, e); RETIRE_FAIL }, + TR_Address(addr, _) => { + let eares : MemoryOpResult(unit) = match (width, sizeof(xlen)) { + (BYTE, _) => mem_write_ea(addr, 1, aq & rl, rl, true), + (HALF, _) => mem_write_ea(addr, 2, aq & rl, rl, true), + (WORD, _) => mem_write_ea(addr, 4, aq & rl, rl, true), + (DOUBLE, 64) => mem_write_ea(addr, 8, aq & rl, rl, true), + _ => internal_error(__FILE__, __LINE__, "Unexpected AMO width") + }; + let is_unsigned : bool = match op { + AMOMINU => true, + AMOMAXU => true, + _ => false + }; + let rs2_val : xlenbits = match width { + BYTE => if is_unsigned then zero_extend(X(rs2)[7..0]) else sign_extend(X(rs2)[7..0]), + HALF => if is_unsigned then zero_extend(X(rs2)[15..0]) else sign_extend(X(rs2)[15..0]), + WORD => if is_unsigned then zero_extend(X(rs2)[31..0]) else sign_extend(X(rs2)[31..0]), + DOUBLE => X(rs2) + }; + match (eares) { + MemException(e) => { handle_mem_exception(vaddr, e); RETIRE_FAIL }, + MemValue(_) => { + let mval : MemoryOpResult(xlenbits) = match (width, sizeof(xlen)) { + (BYTE, _) => extend_value(is_unsigned, mem_read(ReadWrite(Data, Data), addr, 1, aq, aq & rl, true)), + (HALF, _) => extend_value(is_unsigned, mem_read(ReadWrite(Data, Data), addr, 2, aq, aq & rl, true)), + (WORD, _) => extend_value(is_unsigned, mem_read(ReadWrite(Data, Data), addr, 4, aq, aq & rl, true)), + (DOUBLE, 64) => extend_value(is_unsigned, mem_read(ReadWrite(Data, Data), addr, 8, aq, aq & rl, true)), + _ => internal_error(__FILE__, __LINE__, "Unexpected AMO width") + }; + match (mval) { + MemException(e) => { handle_mem_exception(vaddr, e); RETIRE_FAIL }, + MemValue(loaded) => { + let result : xlenbits = + match op { + AMOSWAP => rs2_val, + AMOADD => rs2_val + loaded, + AMOXOR => rs2_val ^ loaded, + AMOAND => rs2_val & loaded, + AMOOR => rs2_val | loaded, + + /* These operations convert bitvectors to integer values using [un]signed, + * and back using to_bits(). + */ + AMOMIN => to_bits(sizeof(xlen), min(signed(rs2_val), signed(loaded))), + AMOMAX => to_bits(sizeof(xlen), max(signed(rs2_val), signed(loaded))), + AMOMINU => to_bits(sizeof(xlen), min(unsigned(rs2_val), unsigned(loaded))), + AMOMAXU => to_bits(sizeof(xlen), max(unsigned(rs2_val), unsigned(loaded))) + }; + let rval : xlenbits = match width { + BYTE => sign_extend(loaded[7..0]), + HALF => sign_extend(loaded[15..0]), + WORD => sign_extend(loaded[31..0]), + DOUBLE => loaded + }; + let wval : MemoryOpResult(bool) = match (width, sizeof(xlen)) { + (BYTE, _) => mem_write_value(addr, 1, result[7..0], aq & rl, rl, true), + (HALF, _) => mem_write_value(addr, 2, result[15..0], aq & rl, rl, true), + (WORD, _) => mem_write_value(addr, 4, result[31..0], aq & rl, rl, true), + (DOUBLE, 64) => mem_write_value(addr, 8, result, aq & rl, rl, true), + _ => internal_error(__FILE__, __LINE__, "Unexpected AMO width") + }; + match (wval) { + MemValue(true) => { X(rd) = rval; RETIRE_SUCCESS }, + MemValue(false) => { internal_error(__FILE__, __LINE__, "AMO got false from mem_write_value") }, + MemException(e) => { handle_mem_exception(vaddr, e); RETIRE_FAIL } + } + } + } + } + } + } + } + } + } + } else { + handle_illegal(); + RETIRE_FAIL + } + } + +# SPDX-SnippetEnd diff --git a/spec/std/isa/inst/Zabha/amoor.h.aqrl.yaml b/spec/std/isa/inst/Zabha/amoor.h.aqrl.yaml new file mode 100644 index 0000000000..33d0425edc --- /dev/null +++ b/spec/std/isa/inst/Zabha/amoor.h.aqrl.yaml @@ -0,0 +1,141 @@ +# Copyright (c) Qualcomm Technologies, Inc. and/or its subsidiaries. + +# WARNING: This file is auto-generated from spec/std/isa/inst/Zaamo/amoor.SIZE.AQRL.layout# Copyright (c) Abhijit Das(Sukuna0007Abhi) +# SPDX-License-Identifier: BSD-3-Clause-Clear + +# yaml-language-server: $schema=../../../../schemas/inst_schema.json + +$schema: "inst_schema.json#" +kind: instruction +name: amoor.h.aqrl +long_name: Atomic fetch-and-or halfword (acquire-release) +description: | + Atomically with acquire and release ordering: + + * Load the halfword at address _xs1_ + * Write the sign-extended value into _xd_ + * OR the least-significant halfword of register _xs2_ to the loaded value + * Write the result to the address in _xs1_ +definedBy: Zabha +assembly: xd, xs2, (xs1) +encoding: + match: 0100011----------001-----0101111 + variables: + - name: xs2 + location: 24-20 + - name: xs1 + location: 19-15 + - name: xd + location: 11-7 +access: + s: always + u: always + vs: always + vu: always +operation(): | + if (!implemented?(ExtensionName::A) || (MISA_CSR_IMPLEMENTED && (CSR[misa].A == 1'b0))) { + raise (ExceptionCode::IllegalInstruction, mode(), $encoding); + } + + memory_model_acquire(); + + XReg virtual_address = X[xs1]; + X[xd] = amo<16>(virtual_address, X[xs2][15:0], AmoOperation::Or, 1'b1, 1'b1, $encoding); + + memory_model_release(); + +# SPDX-SnippetBegin +# SPDX-FileCopyrightText: 2017-2025 Contributors to the RISCV Sail Model +# SPDX-License-Identifier: BSD-2-Clause +sail(): | + { + if extension("A") then { + /* Get the address, X(rs1) (no offset). + * Some extensions perform additional checks on address validity. + */ + match ext_data_get_addr(rs1, zeros(), ReadWrite(Data, Data), width) { + Ext_DataAddr_Error(e) => { ext_handle_data_check_error(e); RETIRE_FAIL }, + Ext_DataAddr_OK(vaddr) => { + match translateAddr(vaddr, ReadWrite(Data, Data)) { + TR_Failure(e, _) => { handle_mem_exception(vaddr, e); RETIRE_FAIL }, + TR_Address(addr, _) => { + let eares : MemoryOpResult(unit) = match (width, sizeof(xlen)) { + (BYTE, _) => mem_write_ea(addr, 1, aq & rl, rl, true), + (HALF, _) => mem_write_ea(addr, 2, aq & rl, rl, true), + (WORD, _) => mem_write_ea(addr, 4, aq & rl, rl, true), + (DOUBLE, 64) => mem_write_ea(addr, 8, aq & rl, rl, true), + _ => internal_error(__FILE__, __LINE__, "Unexpected AMO width") + }; + let is_unsigned : bool = match op { + AMOMINU => true, + AMOMAXU => true, + _ => false + }; + let rs2_val : xlenbits = match width { + BYTE => if is_unsigned then zero_extend(X(rs2)[7..0]) else sign_extend(X(rs2)[7..0]), + HALF => if is_unsigned then zero_extend(X(rs2)[15..0]) else sign_extend(X(rs2)[15..0]), + WORD => if is_unsigned then zero_extend(X(rs2)[31..0]) else sign_extend(X(rs2)[31..0]), + DOUBLE => X(rs2) + }; + match (eares) { + MemException(e) => { handle_mem_exception(vaddr, e); RETIRE_FAIL }, + MemValue(_) => { + let mval : MemoryOpResult(xlenbits) = match (width, sizeof(xlen)) { + (BYTE, _) => extend_value(is_unsigned, mem_read(ReadWrite(Data, Data), addr, 1, aq, aq & rl, true)), + (HALF, _) => extend_value(is_unsigned, mem_read(ReadWrite(Data, Data), addr, 2, aq, aq & rl, true)), + (WORD, _) => extend_value(is_unsigned, mem_read(ReadWrite(Data, Data), addr, 4, aq, aq & rl, true)), + (DOUBLE, 64) => extend_value(is_unsigned, mem_read(ReadWrite(Data, Data), addr, 8, aq, aq & rl, true)), + _ => internal_error(__FILE__, __LINE__, "Unexpected AMO width") + }; + match (mval) { + MemException(e) => { handle_mem_exception(vaddr, e); RETIRE_FAIL }, + MemValue(loaded) => { + let result : xlenbits = + match op { + AMOSWAP => rs2_val, + AMOADD => rs2_val + loaded, + AMOXOR => rs2_val ^ loaded, + AMOAND => rs2_val & loaded, + AMOOR => rs2_val | loaded, + + /* These operations convert bitvectors to integer values using [un]signed, + * and back using to_bits(). + */ + AMOMIN => to_bits(sizeof(xlen), min(signed(rs2_val), signed(loaded))), + AMOMAX => to_bits(sizeof(xlen), max(signed(rs2_val), signed(loaded))), + AMOMINU => to_bits(sizeof(xlen), min(unsigned(rs2_val), unsigned(loaded))), + AMOMAXU => to_bits(sizeof(xlen), max(unsigned(rs2_val), unsigned(loaded))) + }; + let rval : xlenbits = match width { + BYTE => sign_extend(loaded[7..0]), + HALF => sign_extend(loaded[15..0]), + WORD => sign_extend(loaded[31..0]), + DOUBLE => loaded + }; + let wval : MemoryOpResult(bool) = match (width, sizeof(xlen)) { + (BYTE, _) => mem_write_value(addr, 1, result[7..0], aq & rl, rl, true), + (HALF, _) => mem_write_value(addr, 2, result[15..0], aq & rl, rl, true), + (WORD, _) => mem_write_value(addr, 4, result[31..0], aq & rl, rl, true), + (DOUBLE, 64) => mem_write_value(addr, 8, result, aq & rl, rl, true), + _ => internal_error(__FILE__, __LINE__, "Unexpected AMO width") + }; + match (wval) { + MemValue(true) => { X(rd) = rval; RETIRE_SUCCESS }, + MemValue(false) => { internal_error(__FILE__, __LINE__, "AMO got false from mem_write_value") }, + MemException(e) => { handle_mem_exception(vaddr, e); RETIRE_FAIL } + } + } + } + } + } + } + } + } + } + } else { + handle_illegal(); + RETIRE_FAIL + } + } + +# SPDX-SnippetEnd diff --git a/spec/std/isa/inst/Zabha/amoor.h.rl.yaml b/spec/std/isa/inst/Zabha/amoor.h.rl.yaml new file mode 100644 index 0000000000..c78ab2a30c --- /dev/null +++ b/spec/std/isa/inst/Zabha/amoor.h.rl.yaml @@ -0,0 +1,139 @@ +# Copyright (c) Qualcomm Technologies, Inc. and/or its subsidiaries. + +# WARNING: This file is auto-generated from spec/std/isa/inst/Zaamo/amoor.SIZE.AQRL.layout# Copyright (c) Abhijit Das(Sukuna0007Abhi) +# SPDX-License-Identifier: BSD-3-Clause-Clear + +# yaml-language-server: $schema=../../../../schemas/inst_schema.json + +$schema: "inst_schema.json#" +kind: instruction +name: amoor.h.rl +long_name: Atomic fetch-and-or halfword (release) +description: | + Atomically with release ordering: + + * Load the halfword at address _xs1_ + * Write the sign-extended value into _xd_ + * OR the least-significant halfword of register _xs2_ to the loaded value + * Write the result to the address in _xs1_ +definedBy: Zabha +assembly: xd, xs2, (xs1) +encoding: + match: 0100001----------001-----0101111 + variables: + - name: xs2 + location: 24-20 + - name: xs1 + location: 19-15 + - name: xd + location: 11-7 +access: + s: always + u: always + vs: always + vu: always +operation(): | + if (!implemented?(ExtensionName::A) || (MISA_CSR_IMPLEMENTED && (CSR[misa].A == 1'b0))) { + raise (ExceptionCode::IllegalInstruction, mode(), $encoding); + } + + XReg virtual_address = X[xs1]; + X[xd] = amo<16>(virtual_address, X[xs2][15:0], AmoOperation::Or, 1'b0, 1'b1, $encoding); + + memory_model_release(); + +# SPDX-SnippetBegin +# SPDX-FileCopyrightText: 2017-2025 Contributors to the RISCV Sail Model +# SPDX-License-Identifier: BSD-2-Clause +sail(): | + { + if extension("A") then { + /* Get the address, X(rs1) (no offset). + * Some extensions perform additional checks on address validity. + */ + match ext_data_get_addr(rs1, zeros(), ReadWrite(Data, Data), width) { + Ext_DataAddr_Error(e) => { ext_handle_data_check_error(e); RETIRE_FAIL }, + Ext_DataAddr_OK(vaddr) => { + match translateAddr(vaddr, ReadWrite(Data, Data)) { + TR_Failure(e, _) => { handle_mem_exception(vaddr, e); RETIRE_FAIL }, + TR_Address(addr, _) => { + let eares : MemoryOpResult(unit) = match (width, sizeof(xlen)) { + (BYTE, _) => mem_write_ea(addr, 1, aq & rl, rl, true), + (HALF, _) => mem_write_ea(addr, 2, aq & rl, rl, true), + (WORD, _) => mem_write_ea(addr, 4, aq & rl, rl, true), + (DOUBLE, 64) => mem_write_ea(addr, 8, aq & rl, rl, true), + _ => internal_error(__FILE__, __LINE__, "Unexpected AMO width") + }; + let is_unsigned : bool = match op { + AMOMINU => true, + AMOMAXU => true, + _ => false + }; + let rs2_val : xlenbits = match width { + BYTE => if is_unsigned then zero_extend(X(rs2)[7..0]) else sign_extend(X(rs2)[7..0]), + HALF => if is_unsigned then zero_extend(X(rs2)[15..0]) else sign_extend(X(rs2)[15..0]), + WORD => if is_unsigned then zero_extend(X(rs2)[31..0]) else sign_extend(X(rs2)[31..0]), + DOUBLE => X(rs2) + }; + match (eares) { + MemException(e) => { handle_mem_exception(vaddr, e); RETIRE_FAIL }, + MemValue(_) => { + let mval : MemoryOpResult(xlenbits) = match (width, sizeof(xlen)) { + (BYTE, _) => extend_value(is_unsigned, mem_read(ReadWrite(Data, Data), addr, 1, aq, aq & rl, true)), + (HALF, _) => extend_value(is_unsigned, mem_read(ReadWrite(Data, Data), addr, 2, aq, aq & rl, true)), + (WORD, _) => extend_value(is_unsigned, mem_read(ReadWrite(Data, Data), addr, 4, aq, aq & rl, true)), + (DOUBLE, 64) => extend_value(is_unsigned, mem_read(ReadWrite(Data, Data), addr, 8, aq, aq & rl, true)), + _ => internal_error(__FILE__, __LINE__, "Unexpected AMO width") + }; + match (mval) { + MemException(e) => { handle_mem_exception(vaddr, e); RETIRE_FAIL }, + MemValue(loaded) => { + let result : xlenbits = + match op { + AMOSWAP => rs2_val, + AMOADD => rs2_val + loaded, + AMOXOR => rs2_val ^ loaded, + AMOAND => rs2_val & loaded, + AMOOR => rs2_val | loaded, + + /* These operations convert bitvectors to integer values using [un]signed, + * and back using to_bits(). + */ + AMOMIN => to_bits(sizeof(xlen), min(signed(rs2_val), signed(loaded))), + AMOMAX => to_bits(sizeof(xlen), max(signed(rs2_val), signed(loaded))), + AMOMINU => to_bits(sizeof(xlen), min(unsigned(rs2_val), unsigned(loaded))), + AMOMAXU => to_bits(sizeof(xlen), max(unsigned(rs2_val), unsigned(loaded))) + }; + let rval : xlenbits = match width { + BYTE => sign_extend(loaded[7..0]), + HALF => sign_extend(loaded[15..0]), + WORD => sign_extend(loaded[31..0]), + DOUBLE => loaded + }; + let wval : MemoryOpResult(bool) = match (width, sizeof(xlen)) { + (BYTE, _) => mem_write_value(addr, 1, result[7..0], aq & rl, rl, true), + (HALF, _) => mem_write_value(addr, 2, result[15..0], aq & rl, rl, true), + (WORD, _) => mem_write_value(addr, 4, result[31..0], aq & rl, rl, true), + (DOUBLE, 64) => mem_write_value(addr, 8, result, aq & rl, rl, true), + _ => internal_error(__FILE__, __LINE__, "Unexpected AMO width") + }; + match (wval) { + MemValue(true) => { X(rd) = rval; RETIRE_SUCCESS }, + MemValue(false) => { internal_error(__FILE__, __LINE__, "AMO got false from mem_write_value") }, + MemException(e) => { handle_mem_exception(vaddr, e); RETIRE_FAIL } + } + } + } + } + } + } + } + } + } + } else { + handle_illegal(); + RETIRE_FAIL + } + } + +# SPDX-SnippetEnd diff --git a/spec/std/isa/inst/Zabha/amoor.h.yaml b/spec/std/isa/inst/Zabha/amoor.h.yaml index 7c24584708..4cb7c4e0c5 100644 --- a/spec/std/isa/inst/Zabha/amoor.h.yaml +++ b/spec/std/isa/inst/Zabha/amoor.h.yaml @@ -1,4 +1,6 @@ # Copyright (c) Qualcomm Technologies, Inc. and/or its subsidiaries. + +# WARNING: This file is auto-generated from spec/std/isa/inst/Zaamo/amoor.SIZE.AQRL.layout# Copyright (c) Abhijit Das(Sukuna0007Abhi) # SPDX-License-Identifier: BSD-3-Clause-Clear # yaml-language-server: $schema=../../../../schemas/inst_schema.json @@ -6,18 +8,19 @@ $schema: "inst_schema.json#" kind: instruction name: amoor.h -long_name: No synopsis available +long_name: Atomic fetch-and-or halfword description: | - No description available. + Atomically: + + * Load the halfword at address _xs1_ + * Write the sign-extended value into _xd_ + * OR the least-significant halfword of register _xs2_ to the loaded value + * Write the result to the address in _xs1_ definedBy: Zabha assembly: xd, xs2, (xs1) encoding: - match: 01000------------001-----0101111 + match: 0100000----------001-----0101111 variables: - - name: aq - location: 26-26 - - name: rl - location: 25-25 - name: xs2 location: 24-20 - name: xs1 @@ -29,8 +32,13 @@ access: u: always vs: always vu: always -data_independent_timing: false operation(): | + if (!implemented?(ExtensionName::A) || (MISA_CSR_IMPLEMENTED && (CSR[misa].A == 1'b0))) { + raise (ExceptionCode::IllegalInstruction, mode(), $encoding); + } + + XReg virtual_address = X[xs1]; + X[xd] = amo<16>(virtual_address, X[xs2][15:0], AmoOperation::Or, 1'b0, 1'b0, $encoding); # SPDX-SnippetBegin # SPDX-FileCopyrightText: 2017-2025 Contributors to the RISCV Sail Model diff --git a/spec/std/isa/inst/Zabha/amoswap.b.aq.yaml b/spec/std/isa/inst/Zabha/amoswap.b.aq.yaml new file mode 100644 index 0000000000..a8b18f1b35 --- /dev/null +++ b/spec/std/isa/inst/Zabha/amoswap.b.aq.yaml @@ -0,0 +1,138 @@ +# Copyright (c) Qualcomm Technologies, Inc. and/or its subsidiaries. + +# WARNING: This file is auto-generated from spec/std/isa/inst/Zaamo/amoswap.SIZE.AQRL.layout# Copyright (c) Abhijit Das(Sukuna0007Abhi) +# SPDX-License-Identifier: BSD-3-Clause-Clear + +# yaml-language-server: $schema=../../../../schemas/inst_schema.json + +$schema: "inst_schema.json#" +kind: instruction +name: amoswap.b.aq +long_name: Atomic SWAP byte (acquire) +description: | + Atomically with acquire ordering: + + * Load the byte at address _xs1_ + * Write the sign-extended value into _xd_ + * Store the least-significant byte of register _xs2_ to the address in _xs1_ +definedBy: Zabha +assembly: xd, xs2, (xs1) +encoding: + match: 0000110----------000-----0101111 + variables: + - name: xs2 + location: 24-20 + - name: xs1 + location: 19-15 + - name: xd + location: 11-7 +access: + s: always + u: always + vs: always + vu: always +operation(): | + if (!implemented?(ExtensionName::A) || (MISA_CSR_IMPLEMENTED && (CSR[misa].A == 1'b0))) { + raise (ExceptionCode::IllegalInstruction, mode(), $encoding); + } + + memory_model_acquire(); + + XReg virtual_address = X[xs1]; + X[xd] = amo<8>(virtual_address, X[xs2][7:0], AmoOperation::Swap, 1'b1, 1'b0, $encoding); + +# SPDX-SnippetBegin +# SPDX-FileCopyrightText: 2017-2025 Contributors to the RISCV Sail Model +# SPDX-License-Identifier: BSD-2-Clause +sail(): | + { + if extension("A") then { + /* Get the address, X(rs1) (no offset). + * Some extensions perform additional checks on address validity. + */ + match ext_data_get_addr(rs1, zeros(), ReadWrite(Data, Data), width) { + Ext_DataAddr_Error(e) => { ext_handle_data_check_error(e); RETIRE_FAIL }, + Ext_DataAddr_OK(vaddr) => { + match translateAddr(vaddr, ReadWrite(Data, Data)) { + TR_Failure(e, _) => { handle_mem_exception(vaddr, e); RETIRE_FAIL }, + TR_Address(addr, _) => { + let eares : MemoryOpResult(unit) = match (width, sizeof(xlen)) { + (BYTE, _) => mem_write_ea(addr, 1, aq & rl, rl, true), + (HALF, _) => mem_write_ea(addr, 2, aq & rl, rl, true), + (WORD, _) => mem_write_ea(addr, 4, aq & rl, rl, true), + (DOUBLE, 64) => mem_write_ea(addr, 8, aq & rl, rl, true), + _ => internal_error(__FILE__, __LINE__, "Unexpected AMO width") + }; + let is_unsigned : bool = match op { + AMOMINU => true, + AMOMAXU => true, + _ => false + }; + let rs2_val : xlenbits = match width { + BYTE => if is_unsigned then zero_extend(X(rs2)[7..0]) else sign_extend(X(rs2)[7..0]), + HALF => if is_unsigned then zero_extend(X(rs2)[15..0]) else sign_extend(X(rs2)[15..0]), + WORD => if is_unsigned then zero_extend(X(rs2)[31..0]) else sign_extend(X(rs2)[31..0]), + DOUBLE => X(rs2) + }; + match (eares) { + MemException(e) => { handle_mem_exception(vaddr, e); RETIRE_FAIL }, + MemValue(_) => { + let mval : MemoryOpResult(xlenbits) = match (width, sizeof(xlen)) { + (BYTE, _) => extend_value(is_unsigned, mem_read(ReadWrite(Data, Data), addr, 1, aq, aq & rl, true)), + (HALF, _) => extend_value(is_unsigned, mem_read(ReadWrite(Data, Data), addr, 2, aq, aq & rl, true)), + (WORD, _) => extend_value(is_unsigned, mem_read(ReadWrite(Data, Data), addr, 4, aq, aq & rl, true)), + (DOUBLE, 64) => extend_value(is_unsigned, mem_read(ReadWrite(Data, Data), addr, 8, aq, aq & rl, true)), + _ => internal_error(__FILE__, __LINE__, "Unexpected AMO width") + }; + match (mval) { + MemException(e) => { handle_mem_exception(vaddr, e); RETIRE_FAIL }, + MemValue(loaded) => { + let result : xlenbits = + match op { + AMOSWAP => rs2_val, + AMOADD => rs2_val + loaded, + AMOXOR => rs2_val ^ loaded, + AMOAND => rs2_val & loaded, + AMOOR => rs2_val | loaded, + + /* These operations convert bitvectors to integer values using [un]signed, + * and back using to_bits(). + */ + AMOMIN => to_bits(sizeof(xlen), min(signed(rs2_val), signed(loaded))), + AMOMAX => to_bits(sizeof(xlen), max(signed(rs2_val), signed(loaded))), + AMOMINU => to_bits(sizeof(xlen), min(unsigned(rs2_val), unsigned(loaded))), + AMOMAXU => to_bits(sizeof(xlen), max(unsigned(rs2_val), unsigned(loaded))) + }; + let rval : xlenbits = match width { + BYTE => sign_extend(loaded[7..0]), + HALF => sign_extend(loaded[15..0]), + WORD => sign_extend(loaded[31..0]), + DOUBLE => loaded + }; + let wval : MemoryOpResult(bool) = match (width, sizeof(xlen)) { + (BYTE, _) => mem_write_value(addr, 1, result[7..0], aq & rl, rl, true), + (HALF, _) => mem_write_value(addr, 2, result[15..0], aq & rl, rl, true), + (WORD, _) => mem_write_value(addr, 4, result[31..0], aq & rl, rl, true), + (DOUBLE, 64) => mem_write_value(addr, 8, result, aq & rl, rl, true), + _ => internal_error(__FILE__, __LINE__, "Unexpected AMO width") + }; + match (wval) { + MemValue(true) => { X(rd) = rval; RETIRE_SUCCESS }, + MemValue(false) => { internal_error(__FILE__, __LINE__, "AMO got false from mem_write_value") }, + MemException(e) => { handle_mem_exception(vaddr, e); RETIRE_FAIL } + } + } + } + } + } + } + } + } + } + } else { + handle_illegal(); + RETIRE_FAIL + } + } + +# SPDX-SnippetEnd diff --git a/spec/std/isa/inst/Zabha/amoswap.b.aqrl.yaml b/spec/std/isa/inst/Zabha/amoswap.b.aqrl.yaml new file mode 100644 index 0000000000..4388f2e115 --- /dev/null +++ b/spec/std/isa/inst/Zabha/amoswap.b.aqrl.yaml @@ -0,0 +1,140 @@ +# Copyright (c) Qualcomm Technologies, Inc. and/or its subsidiaries. + +# WARNING: This file is auto-generated from spec/std/isa/inst/Zaamo/amoswap.SIZE.AQRL.layout# Copyright (c) Abhijit Das(Sukuna0007Abhi) +# SPDX-License-Identifier: BSD-3-Clause-Clear + +# yaml-language-server: $schema=../../../../schemas/inst_schema.json + +$schema: "inst_schema.json#" +kind: instruction +name: amoswap.b.aqrl +long_name: Atomic SWAP byte (acquire-release) +description: | + Atomically with acquire and release ordering: + + * Load the byte at address _xs1_ + * Write the sign-extended value into _xd_ + * Store the least-significant byte of register _xs2_ to the address in _xs1_ +definedBy: Zabha +assembly: xd, xs2, (xs1) +encoding: + match: 0000111----------000-----0101111 + variables: + - name: xs2 + location: 24-20 + - name: xs1 + location: 19-15 + - name: xd + location: 11-7 +access: + s: always + u: always + vs: always + vu: always +operation(): | + if (!implemented?(ExtensionName::A) || (MISA_CSR_IMPLEMENTED && (CSR[misa].A == 1'b0))) { + raise (ExceptionCode::IllegalInstruction, mode(), $encoding); + } + + memory_model_acquire(); + + XReg virtual_address = X[xs1]; + X[xd] = amo<8>(virtual_address, X[xs2][7:0], AmoOperation::Swap, 1'b1, 1'b1, $encoding); + + memory_model_release(); + +# SPDX-SnippetBegin +# SPDX-FileCopyrightText: 2017-2025 Contributors to the RISCV Sail Model +# SPDX-License-Identifier: BSD-2-Clause +sail(): | + { + if extension("A") then { + /* Get the address, X(rs1) (no offset). + * Some extensions perform additional checks on address validity. + */ + match ext_data_get_addr(rs1, zeros(), ReadWrite(Data, Data), width) { + Ext_DataAddr_Error(e) => { ext_handle_data_check_error(e); RETIRE_FAIL }, + Ext_DataAddr_OK(vaddr) => { + match translateAddr(vaddr, ReadWrite(Data, Data)) { + TR_Failure(e, _) => { handle_mem_exception(vaddr, e); RETIRE_FAIL }, + TR_Address(addr, _) => { + let eares : MemoryOpResult(unit) = match (width, sizeof(xlen)) { + (BYTE, _) => mem_write_ea(addr, 1, aq & rl, rl, true), + (HALF, _) => mem_write_ea(addr, 2, aq & rl, rl, true), + (WORD, _) => mem_write_ea(addr, 4, aq & rl, rl, true), + (DOUBLE, 64) => mem_write_ea(addr, 8, aq & rl, rl, true), + _ => internal_error(__FILE__, __LINE__, "Unexpected AMO width") + }; + let is_unsigned : bool = match op { + AMOMINU => true, + AMOMAXU => true, + _ => false + }; + let rs2_val : xlenbits = match width { + BYTE => if is_unsigned then zero_extend(X(rs2)[7..0]) else sign_extend(X(rs2)[7..0]), + HALF => if is_unsigned then zero_extend(X(rs2)[15..0]) else sign_extend(X(rs2)[15..0]), + WORD => if is_unsigned then zero_extend(X(rs2)[31..0]) else sign_extend(X(rs2)[31..0]), + DOUBLE => X(rs2) + }; + match (eares) { + MemException(e) => { handle_mem_exception(vaddr, e); RETIRE_FAIL }, + MemValue(_) => { + let mval : MemoryOpResult(xlenbits) = match (width, sizeof(xlen)) { + (BYTE, _) => extend_value(is_unsigned, mem_read(ReadWrite(Data, Data), addr, 1, aq, aq & rl, true)), + (HALF, _) => extend_value(is_unsigned, mem_read(ReadWrite(Data, Data), addr, 2, aq, aq & rl, true)), + (WORD, _) => extend_value(is_unsigned, mem_read(ReadWrite(Data, Data), addr, 4, aq, aq & rl, true)), + (DOUBLE, 64) => extend_value(is_unsigned, mem_read(ReadWrite(Data, Data), addr, 8, aq, aq & rl, true)), + _ => internal_error(__FILE__, __LINE__, "Unexpected AMO width") + }; + match (mval) { + MemException(e) => { handle_mem_exception(vaddr, e); RETIRE_FAIL }, + MemValue(loaded) => { + let result : xlenbits = + match op { + AMOSWAP => rs2_val, + AMOADD => rs2_val + loaded, + AMOXOR => rs2_val ^ loaded, + AMOAND => rs2_val & loaded, + AMOOR => rs2_val | loaded, + + /* These operations convert bitvectors to integer values using [un]signed, + * and back using to_bits(). + */ + AMOMIN => to_bits(sizeof(xlen), min(signed(rs2_val), signed(loaded))), + AMOMAX => to_bits(sizeof(xlen), max(signed(rs2_val), signed(loaded))), + AMOMINU => to_bits(sizeof(xlen), min(unsigned(rs2_val), unsigned(loaded))), + AMOMAXU => to_bits(sizeof(xlen), max(unsigned(rs2_val), unsigned(loaded))) + }; + let rval : xlenbits = match width { + BYTE => sign_extend(loaded[7..0]), + HALF => sign_extend(loaded[15..0]), + WORD => sign_extend(loaded[31..0]), + DOUBLE => loaded + }; + let wval : MemoryOpResult(bool) = match (width, sizeof(xlen)) { + (BYTE, _) => mem_write_value(addr, 1, result[7..0], aq & rl, rl, true), + (HALF, _) => mem_write_value(addr, 2, result[15..0], aq & rl, rl, true), + (WORD, _) => mem_write_value(addr, 4, result[31..0], aq & rl, rl, true), + (DOUBLE, 64) => mem_write_value(addr, 8, result, aq & rl, rl, true), + _ => internal_error(__FILE__, __LINE__, "Unexpected AMO width") + }; + match (wval) { + MemValue(true) => { X(rd) = rval; RETIRE_SUCCESS }, + MemValue(false) => { internal_error(__FILE__, __LINE__, "AMO got false from mem_write_value") }, + MemException(e) => { handle_mem_exception(vaddr, e); RETIRE_FAIL } + } + } + } + } + } + } + } + } + } + } else { + handle_illegal(); + RETIRE_FAIL + } + } + +# SPDX-SnippetEnd diff --git a/spec/std/isa/inst/Zabha/amoswap.b.rl.yaml b/spec/std/isa/inst/Zabha/amoswap.b.rl.yaml new file mode 100644 index 0000000000..0811419db5 --- /dev/null +++ b/spec/std/isa/inst/Zabha/amoswap.b.rl.yaml @@ -0,0 +1,138 @@ +# Copyright (c) Qualcomm Technologies, Inc. and/or its subsidiaries. + +# WARNING: This file is auto-generated from spec/std/isa/inst/Zaamo/amoswap.SIZE.AQRL.layout# Copyright (c) Abhijit Das(Sukuna0007Abhi) +# SPDX-License-Identifier: BSD-3-Clause-Clear + +# yaml-language-server: $schema=../../../../schemas/inst_schema.json + +$schema: "inst_schema.json#" +kind: instruction +name: amoswap.b.rl +long_name: Atomic SWAP byte (release) +description: | + Atomically with release ordering: + + * Load the byte at address _xs1_ + * Write the sign-extended value into _xd_ + * Store the least-significant byte of register _xs2_ to the address in _xs1_ +definedBy: Zabha +assembly: xd, xs2, (xs1) +encoding: + match: 0000101----------000-----0101111 + variables: + - name: xs2 + location: 24-20 + - name: xs1 + location: 19-15 + - name: xd + location: 11-7 +access: + s: always + u: always + vs: always + vu: always +operation(): | + if (!implemented?(ExtensionName::A) || (MISA_CSR_IMPLEMENTED && (CSR[misa].A == 1'b0))) { + raise (ExceptionCode::IllegalInstruction, mode(), $encoding); + } + + XReg virtual_address = X[xs1]; + X[xd] = amo<8>(virtual_address, X[xs2][7:0], AmoOperation::Swap, 1'b0, 1'b1, $encoding); + + memory_model_release(); + +# SPDX-SnippetBegin +# SPDX-FileCopyrightText: 2017-2025 Contributors to the RISCV Sail Model +# SPDX-License-Identifier: BSD-2-Clause +sail(): | + { + if extension("A") then { + /* Get the address, X(rs1) (no offset). + * Some extensions perform additional checks on address validity. + */ + match ext_data_get_addr(rs1, zeros(), ReadWrite(Data, Data), width) { + Ext_DataAddr_Error(e) => { ext_handle_data_check_error(e); RETIRE_FAIL }, + Ext_DataAddr_OK(vaddr) => { + match translateAddr(vaddr, ReadWrite(Data, Data)) { + TR_Failure(e, _) => { handle_mem_exception(vaddr, e); RETIRE_FAIL }, + TR_Address(addr, _) => { + let eares : MemoryOpResult(unit) = match (width, sizeof(xlen)) { + (BYTE, _) => mem_write_ea(addr, 1, aq & rl, rl, true), + (HALF, _) => mem_write_ea(addr, 2, aq & rl, rl, true), + (WORD, _) => mem_write_ea(addr, 4, aq & rl, rl, true), + (DOUBLE, 64) => mem_write_ea(addr, 8, aq & rl, rl, true), + _ => internal_error(__FILE__, __LINE__, "Unexpected AMO width") + }; + let is_unsigned : bool = match op { + AMOMINU => true, + AMOMAXU => true, + _ => false + }; + let rs2_val : xlenbits = match width { + BYTE => if is_unsigned then zero_extend(X(rs2)[7..0]) else sign_extend(X(rs2)[7..0]), + HALF => if is_unsigned then zero_extend(X(rs2)[15..0]) else sign_extend(X(rs2)[15..0]), + WORD => if is_unsigned then zero_extend(X(rs2)[31..0]) else sign_extend(X(rs2)[31..0]), + DOUBLE => X(rs2) + }; + match (eares) { + MemException(e) => { handle_mem_exception(vaddr, e); RETIRE_FAIL }, + MemValue(_) => { + let mval : MemoryOpResult(xlenbits) = match (width, sizeof(xlen)) { + (BYTE, _) => extend_value(is_unsigned, mem_read(ReadWrite(Data, Data), addr, 1, aq, aq & rl, true)), + (HALF, _) => extend_value(is_unsigned, mem_read(ReadWrite(Data, Data), addr, 2, aq, aq & rl, true)), + (WORD, _) => extend_value(is_unsigned, mem_read(ReadWrite(Data, Data), addr, 4, aq, aq & rl, true)), + (DOUBLE, 64) => extend_value(is_unsigned, mem_read(ReadWrite(Data, Data), addr, 8, aq, aq & rl, true)), + _ => internal_error(__FILE__, __LINE__, "Unexpected AMO width") + }; + match (mval) { + MemException(e) => { handle_mem_exception(vaddr, e); RETIRE_FAIL }, + MemValue(loaded) => { + let result : xlenbits = + match op { + AMOSWAP => rs2_val, + AMOADD => rs2_val + loaded, + AMOXOR => rs2_val ^ loaded, + AMOAND => rs2_val & loaded, + AMOOR => rs2_val | loaded, + + /* These operations convert bitvectors to integer values using [un]signed, + * and back using to_bits(). + */ + AMOMIN => to_bits(sizeof(xlen), min(signed(rs2_val), signed(loaded))), + AMOMAX => to_bits(sizeof(xlen), max(signed(rs2_val), signed(loaded))), + AMOMINU => to_bits(sizeof(xlen), min(unsigned(rs2_val), unsigned(loaded))), + AMOMAXU => to_bits(sizeof(xlen), max(unsigned(rs2_val), unsigned(loaded))) + }; + let rval : xlenbits = match width { + BYTE => sign_extend(loaded[7..0]), + HALF => sign_extend(loaded[15..0]), + WORD => sign_extend(loaded[31..0]), + DOUBLE => loaded + }; + let wval : MemoryOpResult(bool) = match (width, sizeof(xlen)) { + (BYTE, _) => mem_write_value(addr, 1, result[7..0], aq & rl, rl, true), + (HALF, _) => mem_write_value(addr, 2, result[15..0], aq & rl, rl, true), + (WORD, _) => mem_write_value(addr, 4, result[31..0], aq & rl, rl, true), + (DOUBLE, 64) => mem_write_value(addr, 8, result, aq & rl, rl, true), + _ => internal_error(__FILE__, __LINE__, "Unexpected AMO width") + }; + match (wval) { + MemValue(true) => { X(rd) = rval; RETIRE_SUCCESS }, + MemValue(false) => { internal_error(__FILE__, __LINE__, "AMO got false from mem_write_value") }, + MemException(e) => { handle_mem_exception(vaddr, e); RETIRE_FAIL } + } + } + } + } + } + } + } + } + } + } else { + handle_illegal(); + RETIRE_FAIL + } + } + +# SPDX-SnippetEnd diff --git a/spec/std/isa/inst/Zabha/amoswap.b.yaml b/spec/std/isa/inst/Zabha/amoswap.b.yaml index 15e979ac2a..ea0db40020 100644 --- a/spec/std/isa/inst/Zabha/amoswap.b.yaml +++ b/spec/std/isa/inst/Zabha/amoswap.b.yaml @@ -1,4 +1,6 @@ # Copyright (c) Qualcomm Technologies, Inc. and/or its subsidiaries. + +# WARNING: This file is auto-generated from spec/std/isa/inst/Zaamo/amoswap.SIZE.AQRL.layout# Copyright (c) Abhijit Das(Sukuna0007Abhi) # SPDX-License-Identifier: BSD-3-Clause-Clear # yaml-language-server: $schema=../../../../schemas/inst_schema.json @@ -6,18 +8,18 @@ $schema: "inst_schema.json#" kind: instruction name: amoswap.b -long_name: No synopsis available +long_name: Atomic SWAP byte description: | - No description available. + Atomically: + + * Load the byte at address _xs1_ + * Write the sign-extended value into _xd_ + * Store the least-significant byte of register _xs2_ to the address in _xs1_ definedBy: Zabha assembly: xd, xs2, (xs1) encoding: - match: 00001------------000-----0101111 + match: 0000100----------000-----0101111 variables: - - name: aq - location: 26-26 - - name: rl - location: 25-25 - name: xs2 location: 24-20 - name: xs1 @@ -29,8 +31,13 @@ access: u: always vs: always vu: always -data_independent_timing: false operation(): | + if (!implemented?(ExtensionName::A) || (MISA_CSR_IMPLEMENTED && (CSR[misa].A == 1'b0))) { + raise (ExceptionCode::IllegalInstruction, mode(), $encoding); + } + + XReg virtual_address = X[xs1]; + X[xd] = amo<8>(virtual_address, X[xs2][7:0], AmoOperation::Swap, 1'b0, 1'b0, $encoding); # SPDX-SnippetBegin # SPDX-FileCopyrightText: 2017-2025 Contributors to the RISCV Sail Model diff --git a/spec/std/isa/inst/Zabha/amoswap.h.aq.yaml b/spec/std/isa/inst/Zabha/amoswap.h.aq.yaml new file mode 100644 index 0000000000..5faeb2ec8c --- /dev/null +++ b/spec/std/isa/inst/Zabha/amoswap.h.aq.yaml @@ -0,0 +1,138 @@ +# Copyright (c) Qualcomm Technologies, Inc. and/or its subsidiaries. + +# WARNING: This file is auto-generated from spec/std/isa/inst/Zaamo/amoswap.SIZE.AQRL.layout# Copyright (c) Abhijit Das(Sukuna0007Abhi) +# SPDX-License-Identifier: BSD-3-Clause-Clear + +# yaml-language-server: $schema=../../../../schemas/inst_schema.json + +$schema: "inst_schema.json#" +kind: instruction +name: amoswap.h.aq +long_name: Atomic SWAP halfword (acquire) +description: | + Atomically with acquire ordering: + + * Load the halfword at address _xs1_ + * Write the sign-extended value into _xd_ + * Store the least-significant halfword of register _xs2_ to the address in _xs1_ +definedBy: Zabha +assembly: xd, xs2, (xs1) +encoding: + match: 0000110----------001-----0101111 + variables: + - name: xs2 + location: 24-20 + - name: xs1 + location: 19-15 + - name: xd + location: 11-7 +access: + s: always + u: always + vs: always + vu: always +operation(): | + if (!implemented?(ExtensionName::A) || (MISA_CSR_IMPLEMENTED && (CSR[misa].A == 1'b0))) { + raise (ExceptionCode::IllegalInstruction, mode(), $encoding); + } + + memory_model_acquire(); + + XReg virtual_address = X[xs1]; + X[xd] = amo<16>(virtual_address, X[xs2][15:0], AmoOperation::Swap, 1'b1, 1'b0, $encoding); + +# SPDX-SnippetBegin +# SPDX-FileCopyrightText: 2017-2025 Contributors to the RISCV Sail Model +# SPDX-License-Identifier: BSD-2-Clause +sail(): | + { + if extension("A") then { + /* Get the address, X(rs1) (no offset). + * Some extensions perform additional checks on address validity. + */ + match ext_data_get_addr(rs1, zeros(), ReadWrite(Data, Data), width) { + Ext_DataAddr_Error(e) => { ext_handle_data_check_error(e); RETIRE_FAIL }, + Ext_DataAddr_OK(vaddr) => { + match translateAddr(vaddr, ReadWrite(Data, Data)) { + TR_Failure(e, _) => { handle_mem_exception(vaddr, e); RETIRE_FAIL }, + TR_Address(addr, _) => { + let eares : MemoryOpResult(unit) = match (width, sizeof(xlen)) { + (BYTE, _) => mem_write_ea(addr, 1, aq & rl, rl, true), + (HALF, _) => mem_write_ea(addr, 2, aq & rl, rl, true), + (WORD, _) => mem_write_ea(addr, 4, aq & rl, rl, true), + (DOUBLE, 64) => mem_write_ea(addr, 8, aq & rl, rl, true), + _ => internal_error(__FILE__, __LINE__, "Unexpected AMO width") + }; + let is_unsigned : bool = match op { + AMOMINU => true, + AMOMAXU => true, + _ => false + }; + let rs2_val : xlenbits = match width { + BYTE => if is_unsigned then zero_extend(X(rs2)[7..0]) else sign_extend(X(rs2)[7..0]), + HALF => if is_unsigned then zero_extend(X(rs2)[15..0]) else sign_extend(X(rs2)[15..0]), + WORD => if is_unsigned then zero_extend(X(rs2)[31..0]) else sign_extend(X(rs2)[31..0]), + DOUBLE => X(rs2) + }; + match (eares) { + MemException(e) => { handle_mem_exception(vaddr, e); RETIRE_FAIL }, + MemValue(_) => { + let mval : MemoryOpResult(xlenbits) = match (width, sizeof(xlen)) { + (BYTE, _) => extend_value(is_unsigned, mem_read(ReadWrite(Data, Data), addr, 1, aq, aq & rl, true)), + (HALF, _) => extend_value(is_unsigned, mem_read(ReadWrite(Data, Data), addr, 2, aq, aq & rl, true)), + (WORD, _) => extend_value(is_unsigned, mem_read(ReadWrite(Data, Data), addr, 4, aq, aq & rl, true)), + (DOUBLE, 64) => extend_value(is_unsigned, mem_read(ReadWrite(Data, Data), addr, 8, aq, aq & rl, true)), + _ => internal_error(__FILE__, __LINE__, "Unexpected AMO width") + }; + match (mval) { + MemException(e) => { handle_mem_exception(vaddr, e); RETIRE_FAIL }, + MemValue(loaded) => { + let result : xlenbits = + match op { + AMOSWAP => rs2_val, + AMOADD => rs2_val + loaded, + AMOXOR => rs2_val ^ loaded, + AMOAND => rs2_val & loaded, + AMOOR => rs2_val | loaded, + + /* These operations convert bitvectors to integer values using [un]signed, + * and back using to_bits(). + */ + AMOMIN => to_bits(sizeof(xlen), min(signed(rs2_val), signed(loaded))), + AMOMAX => to_bits(sizeof(xlen), max(signed(rs2_val), signed(loaded))), + AMOMINU => to_bits(sizeof(xlen), min(unsigned(rs2_val), unsigned(loaded))), + AMOMAXU => to_bits(sizeof(xlen), max(unsigned(rs2_val), unsigned(loaded))) + }; + let rval : xlenbits = match width { + BYTE => sign_extend(loaded[7..0]), + HALF => sign_extend(loaded[15..0]), + WORD => sign_extend(loaded[31..0]), + DOUBLE => loaded + }; + let wval : MemoryOpResult(bool) = match (width, sizeof(xlen)) { + (BYTE, _) => mem_write_value(addr, 1, result[7..0], aq & rl, rl, true), + (HALF, _) => mem_write_value(addr, 2, result[15..0], aq & rl, rl, true), + (WORD, _) => mem_write_value(addr, 4, result[31..0], aq & rl, rl, true), + (DOUBLE, 64) => mem_write_value(addr, 8, result, aq & rl, rl, true), + _ => internal_error(__FILE__, __LINE__, "Unexpected AMO width") + }; + match (wval) { + MemValue(true) => { X(rd) = rval; RETIRE_SUCCESS }, + MemValue(false) => { internal_error(__FILE__, __LINE__, "AMO got false from mem_write_value") }, + MemException(e) => { handle_mem_exception(vaddr, e); RETIRE_FAIL } + } + } + } + } + } + } + } + } + } + } else { + handle_illegal(); + RETIRE_FAIL + } + } + +# SPDX-SnippetEnd diff --git a/spec/std/isa/inst/Zabha/amoswap.h.aqrl.yaml b/spec/std/isa/inst/Zabha/amoswap.h.aqrl.yaml new file mode 100644 index 0000000000..578290496a --- /dev/null +++ b/spec/std/isa/inst/Zabha/amoswap.h.aqrl.yaml @@ -0,0 +1,140 @@ +# Copyright (c) Qualcomm Technologies, Inc. and/or its subsidiaries. + +# WARNING: This file is auto-generated from spec/std/isa/inst/Zaamo/amoswap.SIZE.AQRL.layout# Copyright (c) Abhijit Das(Sukuna0007Abhi) +# SPDX-License-Identifier: BSD-3-Clause-Clear + +# yaml-language-server: $schema=../../../../schemas/inst_schema.json + +$schema: "inst_schema.json#" +kind: instruction +name: amoswap.h.aqrl +long_name: Atomic SWAP halfword (acquire-release) +description: | + Atomically with acquire and release ordering: + + * Load the halfword at address _xs1_ + * Write the sign-extended value into _xd_ + * Store the least-significant halfword of register _xs2_ to the address in _xs1_ +definedBy: Zabha +assembly: xd, xs2, (xs1) +encoding: + match: 0000111----------001-----0101111 + variables: + - name: xs2 + location: 24-20 + - name: xs1 + location: 19-15 + - name: xd + location: 11-7 +access: + s: always + u: always + vs: always + vu: always +operation(): | + if (!implemented?(ExtensionName::A) || (MISA_CSR_IMPLEMENTED && (CSR[misa].A == 1'b0))) { + raise (ExceptionCode::IllegalInstruction, mode(), $encoding); + } + + memory_model_acquire(); + + XReg virtual_address = X[xs1]; + X[xd] = amo<16>(virtual_address, X[xs2][15:0], AmoOperation::Swap, 1'b1, 1'b1, $encoding); + + memory_model_release(); + +# SPDX-SnippetBegin +# SPDX-FileCopyrightText: 2017-2025 Contributors to the RISCV Sail Model +# SPDX-License-Identifier: BSD-2-Clause +sail(): | + { + if extension("A") then { + /* Get the address, X(rs1) (no offset). + * Some extensions perform additional checks on address validity. + */ + match ext_data_get_addr(rs1, zeros(), ReadWrite(Data, Data), width) { + Ext_DataAddr_Error(e) => { ext_handle_data_check_error(e); RETIRE_FAIL }, + Ext_DataAddr_OK(vaddr) => { + match translateAddr(vaddr, ReadWrite(Data, Data)) { + TR_Failure(e, _) => { handle_mem_exception(vaddr, e); RETIRE_FAIL }, + TR_Address(addr, _) => { + let eares : MemoryOpResult(unit) = match (width, sizeof(xlen)) { + (BYTE, _) => mem_write_ea(addr, 1, aq & rl, rl, true), + (HALF, _) => mem_write_ea(addr, 2, aq & rl, rl, true), + (WORD, _) => mem_write_ea(addr, 4, aq & rl, rl, true), + (DOUBLE, 64) => mem_write_ea(addr, 8, aq & rl, rl, true), + _ => internal_error(__FILE__, __LINE__, "Unexpected AMO width") + }; + let is_unsigned : bool = match op { + AMOMINU => true, + AMOMAXU => true, + _ => false + }; + let rs2_val : xlenbits = match width { + BYTE => if is_unsigned then zero_extend(X(rs2)[7..0]) else sign_extend(X(rs2)[7..0]), + HALF => if is_unsigned then zero_extend(X(rs2)[15..0]) else sign_extend(X(rs2)[15..0]), + WORD => if is_unsigned then zero_extend(X(rs2)[31..0]) else sign_extend(X(rs2)[31..0]), + DOUBLE => X(rs2) + }; + match (eares) { + MemException(e) => { handle_mem_exception(vaddr, e); RETIRE_FAIL }, + MemValue(_) => { + let mval : MemoryOpResult(xlenbits) = match (width, sizeof(xlen)) { + (BYTE, _) => extend_value(is_unsigned, mem_read(ReadWrite(Data, Data), addr, 1, aq, aq & rl, true)), + (HALF, _) => extend_value(is_unsigned, mem_read(ReadWrite(Data, Data), addr, 2, aq, aq & rl, true)), + (WORD, _) => extend_value(is_unsigned, mem_read(ReadWrite(Data, Data), addr, 4, aq, aq & rl, true)), + (DOUBLE, 64) => extend_value(is_unsigned, mem_read(ReadWrite(Data, Data), addr, 8, aq, aq & rl, true)), + _ => internal_error(__FILE__, __LINE__, "Unexpected AMO width") + }; + match (mval) { + MemException(e) => { handle_mem_exception(vaddr, e); RETIRE_FAIL }, + MemValue(loaded) => { + let result : xlenbits = + match op { + AMOSWAP => rs2_val, + AMOADD => rs2_val + loaded, + AMOXOR => rs2_val ^ loaded, + AMOAND => rs2_val & loaded, + AMOOR => rs2_val | loaded, + + /* These operations convert bitvectors to integer values using [un]signed, + * and back using to_bits(). + */ + AMOMIN => to_bits(sizeof(xlen), min(signed(rs2_val), signed(loaded))), + AMOMAX => to_bits(sizeof(xlen), max(signed(rs2_val), signed(loaded))), + AMOMINU => to_bits(sizeof(xlen), min(unsigned(rs2_val), unsigned(loaded))), + AMOMAXU => to_bits(sizeof(xlen), max(unsigned(rs2_val), unsigned(loaded))) + }; + let rval : xlenbits = match width { + BYTE => sign_extend(loaded[7..0]), + HALF => sign_extend(loaded[15..0]), + WORD => sign_extend(loaded[31..0]), + DOUBLE => loaded + }; + let wval : MemoryOpResult(bool) = match (width, sizeof(xlen)) { + (BYTE, _) => mem_write_value(addr, 1, result[7..0], aq & rl, rl, true), + (HALF, _) => mem_write_value(addr, 2, result[15..0], aq & rl, rl, true), + (WORD, _) => mem_write_value(addr, 4, result[31..0], aq & rl, rl, true), + (DOUBLE, 64) => mem_write_value(addr, 8, result, aq & rl, rl, true), + _ => internal_error(__FILE__, __LINE__, "Unexpected AMO width") + }; + match (wval) { + MemValue(true) => { X(rd) = rval; RETIRE_SUCCESS }, + MemValue(false) => { internal_error(__FILE__, __LINE__, "AMO got false from mem_write_value") }, + MemException(e) => { handle_mem_exception(vaddr, e); RETIRE_FAIL } + } + } + } + } + } + } + } + } + } + } else { + handle_illegal(); + RETIRE_FAIL + } + } + +# SPDX-SnippetEnd diff --git a/spec/std/isa/inst/Zabha/amoswap.h.rl.yaml b/spec/std/isa/inst/Zabha/amoswap.h.rl.yaml new file mode 100644 index 0000000000..d5fe803a92 --- /dev/null +++ b/spec/std/isa/inst/Zabha/amoswap.h.rl.yaml @@ -0,0 +1,138 @@ +# Copyright (c) Qualcomm Technologies, Inc. and/or its subsidiaries. + +# WARNING: This file is auto-generated from spec/std/isa/inst/Zaamo/amoswap.SIZE.AQRL.layout# Copyright (c) Abhijit Das(Sukuna0007Abhi) +# SPDX-License-Identifier: BSD-3-Clause-Clear + +# yaml-language-server: $schema=../../../../schemas/inst_schema.json + +$schema: "inst_schema.json#" +kind: instruction +name: amoswap.h.rl +long_name: Atomic SWAP halfword (release) +description: | + Atomically with release ordering: + + * Load the halfword at address _xs1_ + * Write the sign-extended value into _xd_ + * Store the least-significant halfword of register _xs2_ to the address in _xs1_ +definedBy: Zabha +assembly: xd, xs2, (xs1) +encoding: + match: 0000101----------001-----0101111 + variables: + - name: xs2 + location: 24-20 + - name: xs1 + location: 19-15 + - name: xd + location: 11-7 +access: + s: always + u: always + vs: always + vu: always +operation(): | + if (!implemented?(ExtensionName::A) || (MISA_CSR_IMPLEMENTED && (CSR[misa].A == 1'b0))) { + raise (ExceptionCode::IllegalInstruction, mode(), $encoding); + } + + XReg virtual_address = X[xs1]; + X[xd] = amo<16>(virtual_address, X[xs2][15:0], AmoOperation::Swap, 1'b0, 1'b1, $encoding); + + memory_model_release(); + +# SPDX-SnippetBegin +# SPDX-FileCopyrightText: 2017-2025 Contributors to the RISCV Sail Model +# SPDX-License-Identifier: BSD-2-Clause +sail(): | + { + if extension("A") then { + /* Get the address, X(rs1) (no offset). + * Some extensions perform additional checks on address validity. + */ + match ext_data_get_addr(rs1, zeros(), ReadWrite(Data, Data), width) { + Ext_DataAddr_Error(e) => { ext_handle_data_check_error(e); RETIRE_FAIL }, + Ext_DataAddr_OK(vaddr) => { + match translateAddr(vaddr, ReadWrite(Data, Data)) { + TR_Failure(e, _) => { handle_mem_exception(vaddr, e); RETIRE_FAIL }, + TR_Address(addr, _) => { + let eares : MemoryOpResult(unit) = match (width, sizeof(xlen)) { + (BYTE, _) => mem_write_ea(addr, 1, aq & rl, rl, true), + (HALF, _) => mem_write_ea(addr, 2, aq & rl, rl, true), + (WORD, _) => mem_write_ea(addr, 4, aq & rl, rl, true), + (DOUBLE, 64) => mem_write_ea(addr, 8, aq & rl, rl, true), + _ => internal_error(__FILE__, __LINE__, "Unexpected AMO width") + }; + let is_unsigned : bool = match op { + AMOMINU => true, + AMOMAXU => true, + _ => false + }; + let rs2_val : xlenbits = match width { + BYTE => if is_unsigned then zero_extend(X(rs2)[7..0]) else sign_extend(X(rs2)[7..0]), + HALF => if is_unsigned then zero_extend(X(rs2)[15..0]) else sign_extend(X(rs2)[15..0]), + WORD => if is_unsigned then zero_extend(X(rs2)[31..0]) else sign_extend(X(rs2)[31..0]), + DOUBLE => X(rs2) + }; + match (eares) { + MemException(e) => { handle_mem_exception(vaddr, e); RETIRE_FAIL }, + MemValue(_) => { + let mval : MemoryOpResult(xlenbits) = match (width, sizeof(xlen)) { + (BYTE, _) => extend_value(is_unsigned, mem_read(ReadWrite(Data, Data), addr, 1, aq, aq & rl, true)), + (HALF, _) => extend_value(is_unsigned, mem_read(ReadWrite(Data, Data), addr, 2, aq, aq & rl, true)), + (WORD, _) => extend_value(is_unsigned, mem_read(ReadWrite(Data, Data), addr, 4, aq, aq & rl, true)), + (DOUBLE, 64) => extend_value(is_unsigned, mem_read(ReadWrite(Data, Data), addr, 8, aq, aq & rl, true)), + _ => internal_error(__FILE__, __LINE__, "Unexpected AMO width") + }; + match (mval) { + MemException(e) => { handle_mem_exception(vaddr, e); RETIRE_FAIL }, + MemValue(loaded) => { + let result : xlenbits = + match op { + AMOSWAP => rs2_val, + AMOADD => rs2_val + loaded, + AMOXOR => rs2_val ^ loaded, + AMOAND => rs2_val & loaded, + AMOOR => rs2_val | loaded, + + /* These operations convert bitvectors to integer values using [un]signed, + * and back using to_bits(). + */ + AMOMIN => to_bits(sizeof(xlen), min(signed(rs2_val), signed(loaded))), + AMOMAX => to_bits(sizeof(xlen), max(signed(rs2_val), signed(loaded))), + AMOMINU => to_bits(sizeof(xlen), min(unsigned(rs2_val), unsigned(loaded))), + AMOMAXU => to_bits(sizeof(xlen), max(unsigned(rs2_val), unsigned(loaded))) + }; + let rval : xlenbits = match width { + BYTE => sign_extend(loaded[7..0]), + HALF => sign_extend(loaded[15..0]), + WORD => sign_extend(loaded[31..0]), + DOUBLE => loaded + }; + let wval : MemoryOpResult(bool) = match (width, sizeof(xlen)) { + (BYTE, _) => mem_write_value(addr, 1, result[7..0], aq & rl, rl, true), + (HALF, _) => mem_write_value(addr, 2, result[15..0], aq & rl, rl, true), + (WORD, _) => mem_write_value(addr, 4, result[31..0], aq & rl, rl, true), + (DOUBLE, 64) => mem_write_value(addr, 8, result, aq & rl, rl, true), + _ => internal_error(__FILE__, __LINE__, "Unexpected AMO width") + }; + match (wval) { + MemValue(true) => { X(rd) = rval; RETIRE_SUCCESS }, + MemValue(false) => { internal_error(__FILE__, __LINE__, "AMO got false from mem_write_value") }, + MemException(e) => { handle_mem_exception(vaddr, e); RETIRE_FAIL } + } + } + } + } + } + } + } + } + } + } else { + handle_illegal(); + RETIRE_FAIL + } + } + +# SPDX-SnippetEnd diff --git a/spec/std/isa/inst/Zabha/amoswap.h.yaml b/spec/std/isa/inst/Zabha/amoswap.h.yaml index b3a97988b6..5531ee36e6 100644 --- a/spec/std/isa/inst/Zabha/amoswap.h.yaml +++ b/spec/std/isa/inst/Zabha/amoswap.h.yaml @@ -1,4 +1,6 @@ # Copyright (c) Qualcomm Technologies, Inc. and/or its subsidiaries. + +# WARNING: This file is auto-generated from spec/std/isa/inst/Zaamo/amoswap.SIZE.AQRL.layout# Copyright (c) Abhijit Das(Sukuna0007Abhi) # SPDX-License-Identifier: BSD-3-Clause-Clear # yaml-language-server: $schema=../../../../schemas/inst_schema.json @@ -6,18 +8,18 @@ $schema: "inst_schema.json#" kind: instruction name: amoswap.h -long_name: No synopsis available +long_name: Atomic SWAP halfword description: | - No description available. + Atomically: + + * Load the halfword at address _xs1_ + * Write the sign-extended value into _xd_ + * Store the least-significant halfword of register _xs2_ to the address in _xs1_ definedBy: Zabha assembly: xd, xs2, (xs1) encoding: - match: 00001------------001-----0101111 + match: 0000100----------001-----0101111 variables: - - name: aq - location: 26-26 - - name: rl - location: 25-25 - name: xs2 location: 24-20 - name: xs1 @@ -29,8 +31,13 @@ access: u: always vs: always vu: always -data_independent_timing: false operation(): | + if (!implemented?(ExtensionName::A) || (MISA_CSR_IMPLEMENTED && (CSR[misa].A == 1'b0))) { + raise (ExceptionCode::IllegalInstruction, mode(), $encoding); + } + + XReg virtual_address = X[xs1]; + X[xd] = amo<16>(virtual_address, X[xs2][15:0], AmoOperation::Swap, 1'b0, 1'b0, $encoding); # SPDX-SnippetBegin # SPDX-FileCopyrightText: 2017-2025 Contributors to the RISCV Sail Model diff --git a/spec/std/isa/inst/Zabha/amoxor.b.aq.yaml b/spec/std/isa/inst/Zabha/amoxor.b.aq.yaml new file mode 100644 index 0000000000..7ca8834d48 --- /dev/null +++ b/spec/std/isa/inst/Zabha/amoxor.b.aq.yaml @@ -0,0 +1,139 @@ +# Copyright (c) Qualcomm Technologies, Inc. and/or its subsidiaries. + +# WARNING: This file is auto-generated from spec/std/isa/inst/Zaamo/amoxor.SIZE.AQRL.layout# Copyright (c) Abhijit Das(Sukuna0007Abhi) +# SPDX-License-Identifier: BSD-3-Clause-Clear + +# yaml-language-server: $schema=../../../../schemas/inst_schema.json + +$schema: "inst_schema.json#" +kind: instruction +name: amoxor.b.aq +long_name: Atomic fetch-and-xor byte (acquire) +description: | + Atomically with acquire ordering: + + * Load the byte at address _xs1_ + * Write the sign-extended value into _xd_ + * XOR the least-significant byte of register _xs2_ to the loaded value + * Write the result to the address in _xs1_ +definedBy: Zabha +assembly: xd, xs2, (xs1) +encoding: + match: 0010010----------000-----0101111 + variables: + - name: xs2 + location: 24-20 + - name: xs1 + location: 19-15 + - name: xd + location: 11-7 +access: + s: always + u: always + vs: always + vu: always +operation(): | + if (!implemented?(ExtensionName::A) || (MISA_CSR_IMPLEMENTED && (CSR[misa].A == 1'b0))) { + raise (ExceptionCode::IllegalInstruction, mode(), $encoding); + } + + memory_model_acquire(); + + XReg virtual_address = X[xs1]; + X[xd] = amo<8>(virtual_address, X[xs2][7:0], AmoOperation::Xor, 1'b1, 1'b0, $encoding); + +# SPDX-SnippetBegin +# SPDX-FileCopyrightText: 2017-2025 Contributors to the RISCV Sail Model +# SPDX-License-Identifier: BSD-2-Clause +sail(): | + { + if extension("A") then { + /* Get the address, X(rs1) (no offset). + * Some extensions perform additional checks on address validity. + */ + match ext_data_get_addr(rs1, zeros(), ReadWrite(Data, Data), width) { + Ext_DataAddr_Error(e) => { ext_handle_data_check_error(e); RETIRE_FAIL }, + Ext_DataAddr_OK(vaddr) => { + match translateAddr(vaddr, ReadWrite(Data, Data)) { + TR_Failure(e, _) => { handle_mem_exception(vaddr, e); RETIRE_FAIL }, + TR_Address(addr, _) => { + let eares : MemoryOpResult(unit) = match (width, sizeof(xlen)) { + (BYTE, _) => mem_write_ea(addr, 1, aq & rl, rl, true), + (HALF, _) => mem_write_ea(addr, 2, aq & rl, rl, true), + (WORD, _) => mem_write_ea(addr, 4, aq & rl, rl, true), + (DOUBLE, 64) => mem_write_ea(addr, 8, aq & rl, rl, true), + _ => internal_error(__FILE__, __LINE__, "Unexpected AMO width") + }; + let is_unsigned : bool = match op { + AMOMINU => true, + AMOMAXU => true, + _ => false + }; + let rs2_val : xlenbits = match width { + BYTE => if is_unsigned then zero_extend(X(rs2)[7..0]) else sign_extend(X(rs2)[7..0]), + HALF => if is_unsigned then zero_extend(X(rs2)[15..0]) else sign_extend(X(rs2)[15..0]), + WORD => if is_unsigned then zero_extend(X(rs2)[31..0]) else sign_extend(X(rs2)[31..0]), + DOUBLE => X(rs2) + }; + match (eares) { + MemException(e) => { handle_mem_exception(vaddr, e); RETIRE_FAIL }, + MemValue(_) => { + let mval : MemoryOpResult(xlenbits) = match (width, sizeof(xlen)) { + (BYTE, _) => extend_value(is_unsigned, mem_read(ReadWrite(Data, Data), addr, 1, aq, aq & rl, true)), + (HALF, _) => extend_value(is_unsigned, mem_read(ReadWrite(Data, Data), addr, 2, aq, aq & rl, true)), + (WORD, _) => extend_value(is_unsigned, mem_read(ReadWrite(Data, Data), addr, 4, aq, aq & rl, true)), + (DOUBLE, 64) => extend_value(is_unsigned, mem_read(ReadWrite(Data, Data), addr, 8, aq, aq & rl, true)), + _ => internal_error(__FILE__, __LINE__, "Unexpected AMO width") + }; + match (mval) { + MemException(e) => { handle_mem_exception(vaddr, e); RETIRE_FAIL }, + MemValue(loaded) => { + let result : xlenbits = + match op { + AMOSWAP => rs2_val, + AMOADD => rs2_val + loaded, + AMOXOR => rs2_val ^ loaded, + AMOAND => rs2_val & loaded, + AMOOR => rs2_val | loaded, + + /* These operations convert bitvectors to integer values using [un]signed, + * and back using to_bits(). + */ + AMOMIN => to_bits(sizeof(xlen), min(signed(rs2_val), signed(loaded))), + AMOMAX => to_bits(sizeof(xlen), max(signed(rs2_val), signed(loaded))), + AMOMINU => to_bits(sizeof(xlen), min(unsigned(rs2_val), unsigned(loaded))), + AMOMAXU => to_bits(sizeof(xlen), max(unsigned(rs2_val), unsigned(loaded))) + }; + let rval : xlenbits = match width { + BYTE => sign_extend(loaded[7..0]), + HALF => sign_extend(loaded[15..0]), + WORD => sign_extend(loaded[31..0]), + DOUBLE => loaded + }; + let wval : MemoryOpResult(bool) = match (width, sizeof(xlen)) { + (BYTE, _) => mem_write_value(addr, 1, result[7..0], aq & rl, rl, true), + (HALF, _) => mem_write_value(addr, 2, result[15..0], aq & rl, rl, true), + (WORD, _) => mem_write_value(addr, 4, result[31..0], aq & rl, rl, true), + (DOUBLE, 64) => mem_write_value(addr, 8, result, aq & rl, rl, true), + _ => internal_error(__FILE__, __LINE__, "Unexpected AMO width") + }; + match (wval) { + MemValue(true) => { X(rd) = rval; RETIRE_SUCCESS }, + MemValue(false) => { internal_error(__FILE__, __LINE__, "AMO got false from mem_write_value") }, + MemException(e) => { handle_mem_exception(vaddr, e); RETIRE_FAIL } + } + } + } + } + } + } + } + } + } + } else { + handle_illegal(); + RETIRE_FAIL + } + } + +# SPDX-SnippetEnd diff --git a/spec/std/isa/inst/Zabha/amoxor.b.aqrl.yaml b/spec/std/isa/inst/Zabha/amoxor.b.aqrl.yaml new file mode 100644 index 0000000000..32f6e49889 --- /dev/null +++ b/spec/std/isa/inst/Zabha/amoxor.b.aqrl.yaml @@ -0,0 +1,141 @@ +# Copyright (c) Qualcomm Technologies, Inc. and/or its subsidiaries. + +# WARNING: This file is auto-generated from spec/std/isa/inst/Zaamo/amoxor.SIZE.AQRL.layout# Copyright (c) Abhijit Das(Sukuna0007Abhi) +# SPDX-License-Identifier: BSD-3-Clause-Clear + +# yaml-language-server: $schema=../../../../schemas/inst_schema.json + +$schema: "inst_schema.json#" +kind: instruction +name: amoxor.b.aqrl +long_name: Atomic fetch-and-xor byte (acquire-release) +description: | + Atomically with acquire and release ordering: + + * Load the byte at address _xs1_ + * Write the sign-extended value into _xd_ + * XOR the least-significant byte of register _xs2_ to the loaded value + * Write the result to the address in _xs1_ +definedBy: Zabha +assembly: xd, xs2, (xs1) +encoding: + match: 0010011----------000-----0101111 + variables: + - name: xs2 + location: 24-20 + - name: xs1 + location: 19-15 + - name: xd + location: 11-7 +access: + s: always + u: always + vs: always + vu: always +operation(): | + if (!implemented?(ExtensionName::A) || (MISA_CSR_IMPLEMENTED && (CSR[misa].A == 1'b0))) { + raise (ExceptionCode::IllegalInstruction, mode(), $encoding); + } + + memory_model_acquire(); + + XReg virtual_address = X[xs1]; + X[xd] = amo<8>(virtual_address, X[xs2][7:0], AmoOperation::Xor, 1'b1, 1'b1, $encoding); + + memory_model_release(); + +# SPDX-SnippetBegin +# SPDX-FileCopyrightText: 2017-2025 Contributors to the RISCV Sail Model +# SPDX-License-Identifier: BSD-2-Clause +sail(): | + { + if extension("A") then { + /* Get the address, X(rs1) (no offset). + * Some extensions perform additional checks on address validity. + */ + match ext_data_get_addr(rs1, zeros(), ReadWrite(Data, Data), width) { + Ext_DataAddr_Error(e) => { ext_handle_data_check_error(e); RETIRE_FAIL }, + Ext_DataAddr_OK(vaddr) => { + match translateAddr(vaddr, ReadWrite(Data, Data)) { + TR_Failure(e, _) => { handle_mem_exception(vaddr, e); RETIRE_FAIL }, + TR_Address(addr, _) => { + let eares : MemoryOpResult(unit) = match (width, sizeof(xlen)) { + (BYTE, _) => mem_write_ea(addr, 1, aq & rl, rl, true), + (HALF, _) => mem_write_ea(addr, 2, aq & rl, rl, true), + (WORD, _) => mem_write_ea(addr, 4, aq & rl, rl, true), + (DOUBLE, 64) => mem_write_ea(addr, 8, aq & rl, rl, true), + _ => internal_error(__FILE__, __LINE__, "Unexpected AMO width") + }; + let is_unsigned : bool = match op { + AMOMINU => true, + AMOMAXU => true, + _ => false + }; + let rs2_val : xlenbits = match width { + BYTE => if is_unsigned then zero_extend(X(rs2)[7..0]) else sign_extend(X(rs2)[7..0]), + HALF => if is_unsigned then zero_extend(X(rs2)[15..0]) else sign_extend(X(rs2)[15..0]), + WORD => if is_unsigned then zero_extend(X(rs2)[31..0]) else sign_extend(X(rs2)[31..0]), + DOUBLE => X(rs2) + }; + match (eares) { + MemException(e) => { handle_mem_exception(vaddr, e); RETIRE_FAIL }, + MemValue(_) => { + let mval : MemoryOpResult(xlenbits) = match (width, sizeof(xlen)) { + (BYTE, _) => extend_value(is_unsigned, mem_read(ReadWrite(Data, Data), addr, 1, aq, aq & rl, true)), + (HALF, _) => extend_value(is_unsigned, mem_read(ReadWrite(Data, Data), addr, 2, aq, aq & rl, true)), + (WORD, _) => extend_value(is_unsigned, mem_read(ReadWrite(Data, Data), addr, 4, aq, aq & rl, true)), + (DOUBLE, 64) => extend_value(is_unsigned, mem_read(ReadWrite(Data, Data), addr, 8, aq, aq & rl, true)), + _ => internal_error(__FILE__, __LINE__, "Unexpected AMO width") + }; + match (mval) { + MemException(e) => { handle_mem_exception(vaddr, e); RETIRE_FAIL }, + MemValue(loaded) => { + let result : xlenbits = + match op { + AMOSWAP => rs2_val, + AMOADD => rs2_val + loaded, + AMOXOR => rs2_val ^ loaded, + AMOAND => rs2_val & loaded, + AMOOR => rs2_val | loaded, + + /* These operations convert bitvectors to integer values using [un]signed, + * and back using to_bits(). + */ + AMOMIN => to_bits(sizeof(xlen), min(signed(rs2_val), signed(loaded))), + AMOMAX => to_bits(sizeof(xlen), max(signed(rs2_val), signed(loaded))), + AMOMINU => to_bits(sizeof(xlen), min(unsigned(rs2_val), unsigned(loaded))), + AMOMAXU => to_bits(sizeof(xlen), max(unsigned(rs2_val), unsigned(loaded))) + }; + let rval : xlenbits = match width { + BYTE => sign_extend(loaded[7..0]), + HALF => sign_extend(loaded[15..0]), + WORD => sign_extend(loaded[31..0]), + DOUBLE => loaded + }; + let wval : MemoryOpResult(bool) = match (width, sizeof(xlen)) { + (BYTE, _) => mem_write_value(addr, 1, result[7..0], aq & rl, rl, true), + (HALF, _) => mem_write_value(addr, 2, result[15..0], aq & rl, rl, true), + (WORD, _) => mem_write_value(addr, 4, result[31..0], aq & rl, rl, true), + (DOUBLE, 64) => mem_write_value(addr, 8, result, aq & rl, rl, true), + _ => internal_error(__FILE__, __LINE__, "Unexpected AMO width") + }; + match (wval) { + MemValue(true) => { X(rd) = rval; RETIRE_SUCCESS }, + MemValue(false) => { internal_error(__FILE__, __LINE__, "AMO got false from mem_write_value") }, + MemException(e) => { handle_mem_exception(vaddr, e); RETIRE_FAIL } + } + } + } + } + } + } + } + } + } + } else { + handle_illegal(); + RETIRE_FAIL + } + } + +# SPDX-SnippetEnd diff --git a/spec/std/isa/inst/Zabha/amoxor.b.rl.yaml b/spec/std/isa/inst/Zabha/amoxor.b.rl.yaml new file mode 100644 index 0000000000..5f58f014a1 --- /dev/null +++ b/spec/std/isa/inst/Zabha/amoxor.b.rl.yaml @@ -0,0 +1,139 @@ +# Copyright (c) Qualcomm Technologies, Inc. and/or its subsidiaries. + +# WARNING: This file is auto-generated from spec/std/isa/inst/Zaamo/amoxor.SIZE.AQRL.layout# Copyright (c) Abhijit Das(Sukuna0007Abhi) +# SPDX-License-Identifier: BSD-3-Clause-Clear + +# yaml-language-server: $schema=../../../../schemas/inst_schema.json + +$schema: "inst_schema.json#" +kind: instruction +name: amoxor.b.rl +long_name: Atomic fetch-and-xor byte (release) +description: | + Atomically with release ordering: + + * Load the byte at address _xs1_ + * Write the sign-extended value into _xd_ + * XOR the least-significant byte of register _xs2_ to the loaded value + * Write the result to the address in _xs1_ +definedBy: Zabha +assembly: xd, xs2, (xs1) +encoding: + match: 0010001----------000-----0101111 + variables: + - name: xs2 + location: 24-20 + - name: xs1 + location: 19-15 + - name: xd + location: 11-7 +access: + s: always + u: always + vs: always + vu: always +operation(): | + if (!implemented?(ExtensionName::A) || (MISA_CSR_IMPLEMENTED && (CSR[misa].A == 1'b0))) { + raise (ExceptionCode::IllegalInstruction, mode(), $encoding); + } + + XReg virtual_address = X[xs1]; + X[xd] = amo<8>(virtual_address, X[xs2][7:0], AmoOperation::Xor, 1'b0, 1'b1, $encoding); + + memory_model_release(); + +# SPDX-SnippetBegin +# SPDX-FileCopyrightText: 2017-2025 Contributors to the RISCV Sail Model +# SPDX-License-Identifier: BSD-2-Clause +sail(): | + { + if extension("A") then { + /* Get the address, X(rs1) (no offset). + * Some extensions perform additional checks on address validity. + */ + match ext_data_get_addr(rs1, zeros(), ReadWrite(Data, Data), width) { + Ext_DataAddr_Error(e) => { ext_handle_data_check_error(e); RETIRE_FAIL }, + Ext_DataAddr_OK(vaddr) => { + match translateAddr(vaddr, ReadWrite(Data, Data)) { + TR_Failure(e, _) => { handle_mem_exception(vaddr, e); RETIRE_FAIL }, + TR_Address(addr, _) => { + let eares : MemoryOpResult(unit) = match (width, sizeof(xlen)) { + (BYTE, _) => mem_write_ea(addr, 1, aq & rl, rl, true), + (HALF, _) => mem_write_ea(addr, 2, aq & rl, rl, true), + (WORD, _) => mem_write_ea(addr, 4, aq & rl, rl, true), + (DOUBLE, 64) => mem_write_ea(addr, 8, aq & rl, rl, true), + _ => internal_error(__FILE__, __LINE__, "Unexpected AMO width") + }; + let is_unsigned : bool = match op { + AMOMINU => true, + AMOMAXU => true, + _ => false + }; + let rs2_val : xlenbits = match width { + BYTE => if is_unsigned then zero_extend(X(rs2)[7..0]) else sign_extend(X(rs2)[7..0]), + HALF => if is_unsigned then zero_extend(X(rs2)[15..0]) else sign_extend(X(rs2)[15..0]), + WORD => if is_unsigned then zero_extend(X(rs2)[31..0]) else sign_extend(X(rs2)[31..0]), + DOUBLE => X(rs2) + }; + match (eares) { + MemException(e) => { handle_mem_exception(vaddr, e); RETIRE_FAIL }, + MemValue(_) => { + let mval : MemoryOpResult(xlenbits) = match (width, sizeof(xlen)) { + (BYTE, _) => extend_value(is_unsigned, mem_read(ReadWrite(Data, Data), addr, 1, aq, aq & rl, true)), + (HALF, _) => extend_value(is_unsigned, mem_read(ReadWrite(Data, Data), addr, 2, aq, aq & rl, true)), + (WORD, _) => extend_value(is_unsigned, mem_read(ReadWrite(Data, Data), addr, 4, aq, aq & rl, true)), + (DOUBLE, 64) => extend_value(is_unsigned, mem_read(ReadWrite(Data, Data), addr, 8, aq, aq & rl, true)), + _ => internal_error(__FILE__, __LINE__, "Unexpected AMO width") + }; + match (mval) { + MemException(e) => { handle_mem_exception(vaddr, e); RETIRE_FAIL }, + MemValue(loaded) => { + let result : xlenbits = + match op { + AMOSWAP => rs2_val, + AMOADD => rs2_val + loaded, + AMOXOR => rs2_val ^ loaded, + AMOAND => rs2_val & loaded, + AMOOR => rs2_val | loaded, + + /* These operations convert bitvectors to integer values using [un]signed, + * and back using to_bits(). + */ + AMOMIN => to_bits(sizeof(xlen), min(signed(rs2_val), signed(loaded))), + AMOMAX => to_bits(sizeof(xlen), max(signed(rs2_val), signed(loaded))), + AMOMINU => to_bits(sizeof(xlen), min(unsigned(rs2_val), unsigned(loaded))), + AMOMAXU => to_bits(sizeof(xlen), max(unsigned(rs2_val), unsigned(loaded))) + }; + let rval : xlenbits = match width { + BYTE => sign_extend(loaded[7..0]), + HALF => sign_extend(loaded[15..0]), + WORD => sign_extend(loaded[31..0]), + DOUBLE => loaded + }; + let wval : MemoryOpResult(bool) = match (width, sizeof(xlen)) { + (BYTE, _) => mem_write_value(addr, 1, result[7..0], aq & rl, rl, true), + (HALF, _) => mem_write_value(addr, 2, result[15..0], aq & rl, rl, true), + (WORD, _) => mem_write_value(addr, 4, result[31..0], aq & rl, rl, true), + (DOUBLE, 64) => mem_write_value(addr, 8, result, aq & rl, rl, true), + _ => internal_error(__FILE__, __LINE__, "Unexpected AMO width") + }; + match (wval) { + MemValue(true) => { X(rd) = rval; RETIRE_SUCCESS }, + MemValue(false) => { internal_error(__FILE__, __LINE__, "AMO got false from mem_write_value") }, + MemException(e) => { handle_mem_exception(vaddr, e); RETIRE_FAIL } + } + } + } + } + } + } + } + } + } + } else { + handle_illegal(); + RETIRE_FAIL + } + } + +# SPDX-SnippetEnd diff --git a/spec/std/isa/inst/Zabha/amoxor.b.yaml b/spec/std/isa/inst/Zabha/amoxor.b.yaml index a1657f875f..2d4622a0e9 100644 --- a/spec/std/isa/inst/Zabha/amoxor.b.yaml +++ b/spec/std/isa/inst/Zabha/amoxor.b.yaml @@ -1,4 +1,6 @@ # Copyright (c) Qualcomm Technologies, Inc. and/or its subsidiaries. + +# WARNING: This file is auto-generated from spec/std/isa/inst/Zaamo/amoxor.SIZE.AQRL.layout# Copyright (c) Abhijit Das(Sukuna0007Abhi) # SPDX-License-Identifier: BSD-3-Clause-Clear # yaml-language-server: $schema=../../../../schemas/inst_schema.json @@ -6,18 +8,19 @@ $schema: "inst_schema.json#" kind: instruction name: amoxor.b -long_name: No synopsis available +long_name: Atomic fetch-and-xor byte description: | - No description available. + Atomically: + + * Load the byte at address _xs1_ + * Write the sign-extended value into _xd_ + * XOR the least-significant byte of register _xs2_ to the loaded value + * Write the result to the address in _xs1_ definedBy: Zabha assembly: xd, xs2, (xs1) encoding: - match: 00100------------000-----0101111 + match: 0010000----------000-----0101111 variables: - - name: aq - location: 26-26 - - name: rl - location: 25-25 - name: xs2 location: 24-20 - name: xs1 @@ -29,8 +32,13 @@ access: u: always vs: always vu: always -data_independent_timing: false operation(): | + if (!implemented?(ExtensionName::A) || (MISA_CSR_IMPLEMENTED && (CSR[misa].A == 1'b0))) { + raise (ExceptionCode::IllegalInstruction, mode(), $encoding); + } + + XReg virtual_address = X[xs1]; + X[xd] = amo<8>(virtual_address, X[xs2][7:0], AmoOperation::Xor, 1'b0, 1'b0, $encoding); # SPDX-SnippetBegin # SPDX-FileCopyrightText: 2017-2025 Contributors to the RISCV Sail Model diff --git a/spec/std/isa/inst/Zabha/amoxor.h.aq.yaml b/spec/std/isa/inst/Zabha/amoxor.h.aq.yaml new file mode 100644 index 0000000000..911f62bab3 --- /dev/null +++ b/spec/std/isa/inst/Zabha/amoxor.h.aq.yaml @@ -0,0 +1,139 @@ +# Copyright (c) Qualcomm Technologies, Inc. and/or its subsidiaries. + +# WARNING: This file is auto-generated from spec/std/isa/inst/Zaamo/amoxor.SIZE.AQRL.layout# Copyright (c) Abhijit Das(Sukuna0007Abhi) +# SPDX-License-Identifier: BSD-3-Clause-Clear + +# yaml-language-server: $schema=../../../../schemas/inst_schema.json + +$schema: "inst_schema.json#" +kind: instruction +name: amoxor.h.aq +long_name: Atomic fetch-and-xor halfword (acquire) +description: | + Atomically with acquire ordering: + + * Load the halfword at address _xs1_ + * Write the sign-extended value into _xd_ + * XOR the least-significant halfword of register _xs2_ to the loaded value + * Write the result to the address in _xs1_ +definedBy: Zabha +assembly: xd, xs2, (xs1) +encoding: + match: 0010010----------001-----0101111 + variables: + - name: xs2 + location: 24-20 + - name: xs1 + location: 19-15 + - name: xd + location: 11-7 +access: + s: always + u: always + vs: always + vu: always +operation(): | + if (!implemented?(ExtensionName::A) || (MISA_CSR_IMPLEMENTED && (CSR[misa].A == 1'b0))) { + raise (ExceptionCode::IllegalInstruction, mode(), $encoding); + } + + memory_model_acquire(); + + XReg virtual_address = X[xs1]; + X[xd] = amo<16>(virtual_address, X[xs2][15:0], AmoOperation::Xor, 1'b1, 1'b0, $encoding); + +# SPDX-SnippetBegin +# SPDX-FileCopyrightText: 2017-2025 Contributors to the RISCV Sail Model +# SPDX-License-Identifier: BSD-2-Clause +sail(): | + { + if extension("A") then { + /* Get the address, X(rs1) (no offset). + * Some extensions perform additional checks on address validity. + */ + match ext_data_get_addr(rs1, zeros(), ReadWrite(Data, Data), width) { + Ext_DataAddr_Error(e) => { ext_handle_data_check_error(e); RETIRE_FAIL }, + Ext_DataAddr_OK(vaddr) => { + match translateAddr(vaddr, ReadWrite(Data, Data)) { + TR_Failure(e, _) => { handle_mem_exception(vaddr, e); RETIRE_FAIL }, + TR_Address(addr, _) => { + let eares : MemoryOpResult(unit) = match (width, sizeof(xlen)) { + (BYTE, _) => mem_write_ea(addr, 1, aq & rl, rl, true), + (HALF, _) => mem_write_ea(addr, 2, aq & rl, rl, true), + (WORD, _) => mem_write_ea(addr, 4, aq & rl, rl, true), + (DOUBLE, 64) => mem_write_ea(addr, 8, aq & rl, rl, true), + _ => internal_error(__FILE__, __LINE__, "Unexpected AMO width") + }; + let is_unsigned : bool = match op { + AMOMINU => true, + AMOMAXU => true, + _ => false + }; + let rs2_val : xlenbits = match width { + BYTE => if is_unsigned then zero_extend(X(rs2)[7..0]) else sign_extend(X(rs2)[7..0]), + HALF => if is_unsigned then zero_extend(X(rs2)[15..0]) else sign_extend(X(rs2)[15..0]), + WORD => if is_unsigned then zero_extend(X(rs2)[31..0]) else sign_extend(X(rs2)[31..0]), + DOUBLE => X(rs2) + }; + match (eares) { + MemException(e) => { handle_mem_exception(vaddr, e); RETIRE_FAIL }, + MemValue(_) => { + let mval : MemoryOpResult(xlenbits) = match (width, sizeof(xlen)) { + (BYTE, _) => extend_value(is_unsigned, mem_read(ReadWrite(Data, Data), addr, 1, aq, aq & rl, true)), + (HALF, _) => extend_value(is_unsigned, mem_read(ReadWrite(Data, Data), addr, 2, aq, aq & rl, true)), + (WORD, _) => extend_value(is_unsigned, mem_read(ReadWrite(Data, Data), addr, 4, aq, aq & rl, true)), + (DOUBLE, 64) => extend_value(is_unsigned, mem_read(ReadWrite(Data, Data), addr, 8, aq, aq & rl, true)), + _ => internal_error(__FILE__, __LINE__, "Unexpected AMO width") + }; + match (mval) { + MemException(e) => { handle_mem_exception(vaddr, e); RETIRE_FAIL }, + MemValue(loaded) => { + let result : xlenbits = + match op { + AMOSWAP => rs2_val, + AMOADD => rs2_val + loaded, + AMOXOR => rs2_val ^ loaded, + AMOAND => rs2_val & loaded, + AMOOR => rs2_val | loaded, + + /* These operations convert bitvectors to integer values using [un]signed, + * and back using to_bits(). + */ + AMOMIN => to_bits(sizeof(xlen), min(signed(rs2_val), signed(loaded))), + AMOMAX => to_bits(sizeof(xlen), max(signed(rs2_val), signed(loaded))), + AMOMINU => to_bits(sizeof(xlen), min(unsigned(rs2_val), unsigned(loaded))), + AMOMAXU => to_bits(sizeof(xlen), max(unsigned(rs2_val), unsigned(loaded))) + }; + let rval : xlenbits = match width { + BYTE => sign_extend(loaded[7..0]), + HALF => sign_extend(loaded[15..0]), + WORD => sign_extend(loaded[31..0]), + DOUBLE => loaded + }; + let wval : MemoryOpResult(bool) = match (width, sizeof(xlen)) { + (BYTE, _) => mem_write_value(addr, 1, result[7..0], aq & rl, rl, true), + (HALF, _) => mem_write_value(addr, 2, result[15..0], aq & rl, rl, true), + (WORD, _) => mem_write_value(addr, 4, result[31..0], aq & rl, rl, true), + (DOUBLE, 64) => mem_write_value(addr, 8, result, aq & rl, rl, true), + _ => internal_error(__FILE__, __LINE__, "Unexpected AMO width") + }; + match (wval) { + MemValue(true) => { X(rd) = rval; RETIRE_SUCCESS }, + MemValue(false) => { internal_error(__FILE__, __LINE__, "AMO got false from mem_write_value") }, + MemException(e) => { handle_mem_exception(vaddr, e); RETIRE_FAIL } + } + } + } + } + } + } + } + } + } + } else { + handle_illegal(); + RETIRE_FAIL + } + } + +# SPDX-SnippetEnd diff --git a/spec/std/isa/inst/Zabha/amoxor.h.aqrl.yaml b/spec/std/isa/inst/Zabha/amoxor.h.aqrl.yaml new file mode 100644 index 0000000000..e41eefd0dd --- /dev/null +++ b/spec/std/isa/inst/Zabha/amoxor.h.aqrl.yaml @@ -0,0 +1,141 @@ +# Copyright (c) Qualcomm Technologies, Inc. and/or its subsidiaries. + +# WARNING: This file is auto-generated from spec/std/isa/inst/Zaamo/amoxor.SIZE.AQRL.layout# Copyright (c) Abhijit Das(Sukuna0007Abhi) +# SPDX-License-Identifier: BSD-3-Clause-Clear + +# yaml-language-server: $schema=../../../../schemas/inst_schema.json + +$schema: "inst_schema.json#" +kind: instruction +name: amoxor.h.aqrl +long_name: Atomic fetch-and-xor halfword (acquire-release) +description: | + Atomically with acquire and release ordering: + + * Load the halfword at address _xs1_ + * Write the sign-extended value into _xd_ + * XOR the least-significant halfword of register _xs2_ to the loaded value + * Write the result to the address in _xs1_ +definedBy: Zabha +assembly: xd, xs2, (xs1) +encoding: + match: 0010011----------001-----0101111 + variables: + - name: xs2 + location: 24-20 + - name: xs1 + location: 19-15 + - name: xd + location: 11-7 +access: + s: always + u: always + vs: always + vu: always +operation(): | + if (!implemented?(ExtensionName::A) || (MISA_CSR_IMPLEMENTED && (CSR[misa].A == 1'b0))) { + raise (ExceptionCode::IllegalInstruction, mode(), $encoding); + } + + memory_model_acquire(); + + XReg virtual_address = X[xs1]; + X[xd] = amo<16>(virtual_address, X[xs2][15:0], AmoOperation::Xor, 1'b1, 1'b1, $encoding); + + memory_model_release(); + +# SPDX-SnippetBegin +# SPDX-FileCopyrightText: 2017-2025 Contributors to the RISCV Sail Model +# SPDX-License-Identifier: BSD-2-Clause +sail(): | + { + if extension("A") then { + /* Get the address, X(rs1) (no offset). + * Some extensions perform additional checks on address validity. + */ + match ext_data_get_addr(rs1, zeros(), ReadWrite(Data, Data), width) { + Ext_DataAddr_Error(e) => { ext_handle_data_check_error(e); RETIRE_FAIL }, + Ext_DataAddr_OK(vaddr) => { + match translateAddr(vaddr, ReadWrite(Data, Data)) { + TR_Failure(e, _) => { handle_mem_exception(vaddr, e); RETIRE_FAIL }, + TR_Address(addr, _) => { + let eares : MemoryOpResult(unit) = match (width, sizeof(xlen)) { + (BYTE, _) => mem_write_ea(addr, 1, aq & rl, rl, true), + (HALF, _) => mem_write_ea(addr, 2, aq & rl, rl, true), + (WORD, _) => mem_write_ea(addr, 4, aq & rl, rl, true), + (DOUBLE, 64) => mem_write_ea(addr, 8, aq & rl, rl, true), + _ => internal_error(__FILE__, __LINE__, "Unexpected AMO width") + }; + let is_unsigned : bool = match op { + AMOMINU => true, + AMOMAXU => true, + _ => false + }; + let rs2_val : xlenbits = match width { + BYTE => if is_unsigned then zero_extend(X(rs2)[7..0]) else sign_extend(X(rs2)[7..0]), + HALF => if is_unsigned then zero_extend(X(rs2)[15..0]) else sign_extend(X(rs2)[15..0]), + WORD => if is_unsigned then zero_extend(X(rs2)[31..0]) else sign_extend(X(rs2)[31..0]), + DOUBLE => X(rs2) + }; + match (eares) { + MemException(e) => { handle_mem_exception(vaddr, e); RETIRE_FAIL }, + MemValue(_) => { + let mval : MemoryOpResult(xlenbits) = match (width, sizeof(xlen)) { + (BYTE, _) => extend_value(is_unsigned, mem_read(ReadWrite(Data, Data), addr, 1, aq, aq & rl, true)), + (HALF, _) => extend_value(is_unsigned, mem_read(ReadWrite(Data, Data), addr, 2, aq, aq & rl, true)), + (WORD, _) => extend_value(is_unsigned, mem_read(ReadWrite(Data, Data), addr, 4, aq, aq & rl, true)), + (DOUBLE, 64) => extend_value(is_unsigned, mem_read(ReadWrite(Data, Data), addr, 8, aq, aq & rl, true)), + _ => internal_error(__FILE__, __LINE__, "Unexpected AMO width") + }; + match (mval) { + MemException(e) => { handle_mem_exception(vaddr, e); RETIRE_FAIL }, + MemValue(loaded) => { + let result : xlenbits = + match op { + AMOSWAP => rs2_val, + AMOADD => rs2_val + loaded, + AMOXOR => rs2_val ^ loaded, + AMOAND => rs2_val & loaded, + AMOOR => rs2_val | loaded, + + /* These operations convert bitvectors to integer values using [un]signed, + * and back using to_bits(). + */ + AMOMIN => to_bits(sizeof(xlen), min(signed(rs2_val), signed(loaded))), + AMOMAX => to_bits(sizeof(xlen), max(signed(rs2_val), signed(loaded))), + AMOMINU => to_bits(sizeof(xlen), min(unsigned(rs2_val), unsigned(loaded))), + AMOMAXU => to_bits(sizeof(xlen), max(unsigned(rs2_val), unsigned(loaded))) + }; + let rval : xlenbits = match width { + BYTE => sign_extend(loaded[7..0]), + HALF => sign_extend(loaded[15..0]), + WORD => sign_extend(loaded[31..0]), + DOUBLE => loaded + }; + let wval : MemoryOpResult(bool) = match (width, sizeof(xlen)) { + (BYTE, _) => mem_write_value(addr, 1, result[7..0], aq & rl, rl, true), + (HALF, _) => mem_write_value(addr, 2, result[15..0], aq & rl, rl, true), + (WORD, _) => mem_write_value(addr, 4, result[31..0], aq & rl, rl, true), + (DOUBLE, 64) => mem_write_value(addr, 8, result, aq & rl, rl, true), + _ => internal_error(__FILE__, __LINE__, "Unexpected AMO width") + }; + match (wval) { + MemValue(true) => { X(rd) = rval; RETIRE_SUCCESS }, + MemValue(false) => { internal_error(__FILE__, __LINE__, "AMO got false from mem_write_value") }, + MemException(e) => { handle_mem_exception(vaddr, e); RETIRE_FAIL } + } + } + } + } + } + } + } + } + } + } else { + handle_illegal(); + RETIRE_FAIL + } + } + +# SPDX-SnippetEnd diff --git a/spec/std/isa/inst/Zabha/amoxor.h.rl.yaml b/spec/std/isa/inst/Zabha/amoxor.h.rl.yaml new file mode 100644 index 0000000000..d8a33ff205 --- /dev/null +++ b/spec/std/isa/inst/Zabha/amoxor.h.rl.yaml @@ -0,0 +1,139 @@ +# Copyright (c) Qualcomm Technologies, Inc. and/or its subsidiaries. + +# WARNING: This file is auto-generated from spec/std/isa/inst/Zaamo/amoxor.SIZE.AQRL.layout# Copyright (c) Abhijit Das(Sukuna0007Abhi) +# SPDX-License-Identifier: BSD-3-Clause-Clear + +# yaml-language-server: $schema=../../../../schemas/inst_schema.json + +$schema: "inst_schema.json#" +kind: instruction +name: amoxor.h.rl +long_name: Atomic fetch-and-xor halfword (release) +description: | + Atomically with release ordering: + + * Load the halfword at address _xs1_ + * Write the sign-extended value into _xd_ + * XOR the least-significant halfword of register _xs2_ to the loaded value + * Write the result to the address in _xs1_ +definedBy: Zabha +assembly: xd, xs2, (xs1) +encoding: + match: 0010001----------001-----0101111 + variables: + - name: xs2 + location: 24-20 + - name: xs1 + location: 19-15 + - name: xd + location: 11-7 +access: + s: always + u: always + vs: always + vu: always +operation(): | + if (!implemented?(ExtensionName::A) || (MISA_CSR_IMPLEMENTED && (CSR[misa].A == 1'b0))) { + raise (ExceptionCode::IllegalInstruction, mode(), $encoding); + } + + XReg virtual_address = X[xs1]; + X[xd] = amo<16>(virtual_address, X[xs2][15:0], AmoOperation::Xor, 1'b0, 1'b1, $encoding); + + memory_model_release(); + +# SPDX-SnippetBegin +# SPDX-FileCopyrightText: 2017-2025 Contributors to the RISCV Sail Model +# SPDX-License-Identifier: BSD-2-Clause +sail(): | + { + if extension("A") then { + /* Get the address, X(rs1) (no offset). + * Some extensions perform additional checks on address validity. + */ + match ext_data_get_addr(rs1, zeros(), ReadWrite(Data, Data), width) { + Ext_DataAddr_Error(e) => { ext_handle_data_check_error(e); RETIRE_FAIL }, + Ext_DataAddr_OK(vaddr) => { + match translateAddr(vaddr, ReadWrite(Data, Data)) { + TR_Failure(e, _) => { handle_mem_exception(vaddr, e); RETIRE_FAIL }, + TR_Address(addr, _) => { + let eares : MemoryOpResult(unit) = match (width, sizeof(xlen)) { + (BYTE, _) => mem_write_ea(addr, 1, aq & rl, rl, true), + (HALF, _) => mem_write_ea(addr, 2, aq & rl, rl, true), + (WORD, _) => mem_write_ea(addr, 4, aq & rl, rl, true), + (DOUBLE, 64) => mem_write_ea(addr, 8, aq & rl, rl, true), + _ => internal_error(__FILE__, __LINE__, "Unexpected AMO width") + }; + let is_unsigned : bool = match op { + AMOMINU => true, + AMOMAXU => true, + _ => false + }; + let rs2_val : xlenbits = match width { + BYTE => if is_unsigned then zero_extend(X(rs2)[7..0]) else sign_extend(X(rs2)[7..0]), + HALF => if is_unsigned then zero_extend(X(rs2)[15..0]) else sign_extend(X(rs2)[15..0]), + WORD => if is_unsigned then zero_extend(X(rs2)[31..0]) else sign_extend(X(rs2)[31..0]), + DOUBLE => X(rs2) + }; + match (eares) { + MemException(e) => { handle_mem_exception(vaddr, e); RETIRE_FAIL }, + MemValue(_) => { + let mval : MemoryOpResult(xlenbits) = match (width, sizeof(xlen)) { + (BYTE, _) => extend_value(is_unsigned, mem_read(ReadWrite(Data, Data), addr, 1, aq, aq & rl, true)), + (HALF, _) => extend_value(is_unsigned, mem_read(ReadWrite(Data, Data), addr, 2, aq, aq & rl, true)), + (WORD, _) => extend_value(is_unsigned, mem_read(ReadWrite(Data, Data), addr, 4, aq, aq & rl, true)), + (DOUBLE, 64) => extend_value(is_unsigned, mem_read(ReadWrite(Data, Data), addr, 8, aq, aq & rl, true)), + _ => internal_error(__FILE__, __LINE__, "Unexpected AMO width") + }; + match (mval) { + MemException(e) => { handle_mem_exception(vaddr, e); RETIRE_FAIL }, + MemValue(loaded) => { + let result : xlenbits = + match op { + AMOSWAP => rs2_val, + AMOADD => rs2_val + loaded, + AMOXOR => rs2_val ^ loaded, + AMOAND => rs2_val & loaded, + AMOOR => rs2_val | loaded, + + /* These operations convert bitvectors to integer values using [un]signed, + * and back using to_bits(). + */ + AMOMIN => to_bits(sizeof(xlen), min(signed(rs2_val), signed(loaded))), + AMOMAX => to_bits(sizeof(xlen), max(signed(rs2_val), signed(loaded))), + AMOMINU => to_bits(sizeof(xlen), min(unsigned(rs2_val), unsigned(loaded))), + AMOMAXU => to_bits(sizeof(xlen), max(unsigned(rs2_val), unsigned(loaded))) + }; + let rval : xlenbits = match width { + BYTE => sign_extend(loaded[7..0]), + HALF => sign_extend(loaded[15..0]), + WORD => sign_extend(loaded[31..0]), + DOUBLE => loaded + }; + let wval : MemoryOpResult(bool) = match (width, sizeof(xlen)) { + (BYTE, _) => mem_write_value(addr, 1, result[7..0], aq & rl, rl, true), + (HALF, _) => mem_write_value(addr, 2, result[15..0], aq & rl, rl, true), + (WORD, _) => mem_write_value(addr, 4, result[31..0], aq & rl, rl, true), + (DOUBLE, 64) => mem_write_value(addr, 8, result, aq & rl, rl, true), + _ => internal_error(__FILE__, __LINE__, "Unexpected AMO width") + }; + match (wval) { + MemValue(true) => { X(rd) = rval; RETIRE_SUCCESS }, + MemValue(false) => { internal_error(__FILE__, __LINE__, "AMO got false from mem_write_value") }, + MemException(e) => { handle_mem_exception(vaddr, e); RETIRE_FAIL } + } + } + } + } + } + } + } + } + } + } else { + handle_illegal(); + RETIRE_FAIL + } + } + +# SPDX-SnippetEnd diff --git a/spec/std/isa/inst/Zabha/amoxor.h.yaml b/spec/std/isa/inst/Zabha/amoxor.h.yaml index d184f00e83..702369ca7e 100644 --- a/spec/std/isa/inst/Zabha/amoxor.h.yaml +++ b/spec/std/isa/inst/Zabha/amoxor.h.yaml @@ -1,4 +1,6 @@ # Copyright (c) Qualcomm Technologies, Inc. and/or its subsidiaries. + +# WARNING: This file is auto-generated from spec/std/isa/inst/Zaamo/amoxor.SIZE.AQRL.layout# Copyright (c) Abhijit Das(Sukuna0007Abhi) # SPDX-License-Identifier: BSD-3-Clause-Clear # yaml-language-server: $schema=../../../../schemas/inst_schema.json @@ -6,18 +8,19 @@ $schema: "inst_schema.json#" kind: instruction name: amoxor.h -long_name: No synopsis available +long_name: Atomic fetch-and-xor halfword description: | - No description available. + Atomically: + + * Load the halfword at address _xs1_ + * Write the sign-extended value into _xd_ + * XOR the least-significant halfword of register _xs2_ to the loaded value + * Write the result to the address in _xs1_ definedBy: Zabha assembly: xd, xs2, (xs1) encoding: - match: 00100------------001-----0101111 + match: 0010000----------001-----0101111 variables: - - name: aq - location: 26-26 - - name: rl - location: 25-25 - name: xs2 location: 24-20 - name: xs1 @@ -29,8 +32,13 @@ access: u: always vs: always vu: always -data_independent_timing: false operation(): | + if (!implemented?(ExtensionName::A) || (MISA_CSR_IMPLEMENTED && (CSR[misa].A == 1'b0))) { + raise (ExceptionCode::IllegalInstruction, mode(), $encoding); + } + + XReg virtual_address = X[xs1]; + X[xd] = amo<16>(virtual_address, X[xs2][15:0], AmoOperation::Xor, 1'b0, 1'b0, $encoding); # SPDX-SnippetBegin # SPDX-FileCopyrightText: 2017-2025 Contributors to the RISCV Sail Model diff --git a/spec/std/isa/inst/Zacas/amocas.SIZE.AQRL.layout b/spec/std/isa/inst/Zacas/amocas.SIZE.AQRL.layout new file mode 100644 index 0000000000..8bc87c0c9e --- /dev/null +++ b/spec/std/isa/inst/Zacas/amocas.SIZE.AQRL.layout @@ -0,0 +1,168 @@ +# Copyright (c) Qualcomm Technologies, Inc. and/or its subsidiaries. +# Copyright (c) Abhijit Das(Sukuna0007Abhi) +# SPDX-License-Identifier: BSD-3-Clause-Clear + +# yaml-language-server: $schema=../../../../schemas/inst_schema.json +<%- + raise "'size' must be defined as 'b', 'h', 'w', 'd', or 'q'" unless %w[b h w d q].include?(size) + raise "'aq' must be defined as true or false" unless [true, false].include?(aq) + raise "'rl' must be defined as true or false" unless [true, false].include?(rl) + + size_info = { + "b" => { name: "byte", bits: 8, funct3: "000", operation_bits: "8", extension: "Zabha" }, + "h" => { name: "halfword", bits: 16, funct3: "001", operation_bits: "16", extension: "Zabha" }, + "w" => { name: "word", bits: 32, funct3: "010", operation_bits: "32", extension: "Zacas" }, + "d" => { name: "doubleword", bits: 64, funct3: "011", operation_bits: "64", extension: "Zacas" }, + "q" => { name: "quadword", bits: 128, funct3: "100", operation_bits: "128", extension: "Zacas" } + } + + current_size = size_info[size] + + # Generate instruction name suffix based on aq/rl + aq_rl_suffix = "" + if aq && rl + aq_rl_suffix = ".aqrl" + elsif aq + aq_rl_suffix = ".aq" + elsif rl + aq_rl_suffix = ".rl" + end + + # Generate match string with fixed aq/rl bits (funct5 = 00101 for amocas) + aq_bit = aq ? "1" : "0" + rl_bit = rl ? "1" : "0" +-%> + +$schema: "inst_schema.json#" +kind: instruction +name: amocas.<%= size %><%= aq_rl_suffix %> +long_name: Atomic compare-and-swap <%= current_size[:name] %><%= aq && rl ? " (acquire-release)" : (aq ? " (acquire)" : (rl ? " (release)" : "")) %> +description: | + Atomically<%= aq && rl ? " with acquire and release ordering" : (aq ? " with acquire ordering" : (rl ? " with release ordering" : "")) %>: + + * Load the <%= current_size[:name] %> at address _xs1_ + * Write the <%= %w[b h w].include?(size) ? "sign-extended value" : "loaded value" %> into _xd_ + * Compare the loaded value with the <%= %w[b h w].include?(size) ? "least-significant #{current_size[:name]} of register" : "value of register" %> _xs2_ + * If equal, write the <%= %w[b h w].include?(size) ? "least-significant #{current_size[:name]} of register" : "value of register" %> _xs2+1_ to the address in _xs1_ +definedBy: <%= current_size[:extension] %> +<%- if %w[d q].include?(size) -%> +base: 64 +<%- end -%> +assembly: xd, xs2, (xs1) +encoding: + match: 00101<%= aq_bit %><%= rl_bit %>----------<%= current_size[:funct3] %>-----0101111 + variables: + - name: xs2 + location: 24-20 + - name: xs1 + location: 19-15 + - name: xd + location: 11-7 +access: + s: always + u: always + vs: always + vu: always +operation(): | + if (!implemented?(ExtensionName::<%= current_size[:extension] %>)) { + raise (ExceptionCode::IllegalInstruction, mode(), $encoding); + } + +<% if aq -%> + memory_model_acquire(); + +<% end -%> + XReg virtual_address = X[xs1]; + # TODO + # X[xd] = amocas<%= current_size[:operation_bits] %>(virtual_address, X[xs2]<%= %w[b h w].include?(size) ? "[#{current_size[:bits]-1}:0]" : "" %>, X[xd]<%= %w[b h w].include?(size) ? "[#{current_size[:bits]-1}:0]" : "" %>, <%= aq ? "1'b1" : "1'b0" %>, <%= rl ? "1'b1" : "1'b0" %>, $encoding); +<% if rl -%> + + memory_model_release(); +<% end -%> + +# SPDX-SnippetBegin +# SPDX-FileCopyrightText: 2017-2025 Contributors to the RISCV Sail Model +# SPDX-License-Identifier: BSD-2-Clause +sail(): | + { + if extension("<%= current_size[:extension] %>") then { + /* Get the address, X(rs1) (no offset). + * Some extensions perform additional checks on address validity. + */ + match ext_data_get_addr(rs1, zeros(), ReadWrite(Data, Data), width) { + Ext_DataAddr_Error(e) => { ext_handle_data_check_error(e); RETIRE_FAIL }, + Ext_DataAddr_OK(vaddr) => { + match translateAddr(vaddr, ReadWrite(Data, Data)) { + TR_Failure(e, _) => { handle_mem_exception(vaddr, e); RETIRE_FAIL }, + TR_Address(addr, _) => { + let eares : MemoryOpResult(unit) = match (width, sizeof(xlen)) { + (BYTE, _) => mem_write_ea(addr, 1, aq & rl, rl, true), + (HALF, _) => mem_write_ea(addr, 2, aq & rl, rl, true), + (WORD, _) => mem_write_ea(addr, 4, aq & rl, rl, true), + (DOUBLE, 64) => mem_write_ea(addr, 8, aq & rl, rl, true), + _ => internal_error(__FILE__, __LINE__, "Unexpected AMOCAS width") + }; + let rs2_val : xlenbits = match width { + BYTE => sign_extend(X(rs2)[7..0]), + HALF => sign_extend(X(rs2)[15..0]), + WORD => sign_extend(X(rs2)[31..0]), + DOUBLE => X(rs2) + }; + let rd_val : xlenbits = match width { + BYTE => sign_extend(X(rd)[7..0]), + HALF => sign_extend(X(rd)[15..0]), + WORD => sign_extend(X(rd)[31..0]), + DOUBLE => X(rd) + }; + match (eares) { + MemException(e) => { handle_mem_exception(vaddr, e); RETIRE_FAIL }, + MemValue(_) => { + let mval : MemoryOpResult(xlenbits) = match (width, sizeof(xlen)) { + (BYTE, _) => extend_value(false, mem_read(ReadWrite(Data, Data), addr, 1, aq, aq & rl, true)), + (HALF, _) => extend_value(false, mem_read(ReadWrite(Data, Data), addr, 2, aq, aq & rl, true)), + (WORD, _) => extend_value(false, mem_read(ReadWrite(Data, Data), addr, 4, aq, aq & rl, true)), + (DOUBLE, 64) => extend_value(false, mem_read(ReadWrite(Data, Data), addr, 8, aq, aq & rl, true)), + _ => internal_error(__FILE__, __LINE__, "Unexpected AMOCAS width") + }; + match (mval) { + MemException(e) => { handle_mem_exception(vaddr, e); RETIRE_FAIL }, + MemValue(loaded) => { + let success : bool = (loaded == rs2_val); + let result : xlenbits = if success then rd_val else loaded; + let rval : xlenbits = match width { + BYTE => sign_extend(loaded[7..0]), + HALF => sign_extend(loaded[15..0]), + WORD => sign_extend(loaded[31..0]), + DOUBLE => loaded + }; + let wval : MemoryOpResult(bool) = if success then { + match (width, sizeof(xlen)) { + (BYTE, _) => mem_write_value(addr, 1, result[7..0], aq & rl, rl, true), + (HALF, _) => mem_write_value(addr, 2, result[15..0], aq & rl, rl, true), + (WORD, _) => mem_write_value(addr, 4, result[31..0], aq & rl, rl, true), + (DOUBLE, 64) => mem_write_value(addr, 8, result, aq & rl, rl, true), + _ => internal_error(__FILE__, __LINE__, "Unexpected AMOCAS width") + } + } else { + MemValue(true) /* No write on compare failure */ + }; + match (wval) { + MemValue(true) => { X(rd) = rval; RETIRE_SUCCESS }, + MemValue(false) => { internal_error(__FILE__, __LINE__, "AMOCAS got false from mem_write_value") }, + MemException(e) => { handle_mem_exception(vaddr, e); RETIRE_FAIL } + } + } + } + } + } + } + } + } + } + } else { + handle_illegal(); + RETIRE_FAIL + } + } + +# SPDX-SnippetEnd diff --git a/spec/std/isa/inst/Zacas/amocas.d.aq.yaml b/spec/std/isa/inst/Zacas/amocas.d.aq.yaml new file mode 100644 index 0000000000..c8e25cef0c --- /dev/null +++ b/spec/std/isa/inst/Zacas/amocas.d.aq.yaml @@ -0,0 +1,132 @@ +# Copyright (c) Qualcomm Technologies, Inc. and/or its subsidiaries. + +# WARNING: This file is auto-generated from spec/std/isa/inst/Zacas/amocas.SIZE.AQRL.layout# Copyright (c) Abhijit Das(Sukuna0007Abhi) +# SPDX-License-Identifier: BSD-3-Clause-Clear + +# yaml-language-server: $schema=../../../../schemas/inst_schema.json + +$schema: "inst_schema.json#" +kind: instruction +name: amocas.d.aq +long_name: Atomic compare-and-swap doubleword (acquire) +description: | + Atomically with acquire ordering: + + * Load the doubleword at address _xs1_ + * Write the loaded value into _xd_ + * Compare the loaded value with the value of register _xs2_ + * If equal, write the value of register _xs2+1_ to the address in _xs1_ +definedBy: Zacas +base: 64 +assembly: xd, xs2, (xs1) +encoding: + match: 0010110----------011-----0101111 + variables: + - name: xs2 + location: 24-20 + - name: xs1 + location: 19-15 + - name: xd + location: 11-7 +access: + s: always + u: always + vs: always + vu: always +operation(): | + if (!implemented?(ExtensionName::Zacas)) { + raise (ExceptionCode::IllegalInstruction, mode(), $encoding); + } + + memory_model_acquire(); + + XReg virtual_address = X[xs1]; + # TODO + # X[xd] = amocas64(virtual_address, X[xs2], X[xd], 1'b1, 1'b0, $encoding); + +# SPDX-SnippetBegin +# SPDX-FileCopyrightText: 2017-2025 Contributors to the RISCV Sail Model +# SPDX-License-Identifier: BSD-2-Clause +sail(): | + { + if extension("Zacas") then { + /* Get the address, X(rs1) (no offset). + * Some extensions perform additional checks on address validity. + */ + match ext_data_get_addr(rs1, zeros(), ReadWrite(Data, Data), width) { + Ext_DataAddr_Error(e) => { ext_handle_data_check_error(e); RETIRE_FAIL }, + Ext_DataAddr_OK(vaddr) => { + match translateAddr(vaddr, ReadWrite(Data, Data)) { + TR_Failure(e, _) => { handle_mem_exception(vaddr, e); RETIRE_FAIL }, + TR_Address(addr, _) => { + let eares : MemoryOpResult(unit) = match (width, sizeof(xlen)) { + (BYTE, _) => mem_write_ea(addr, 1, aq & rl, rl, true), + (HALF, _) => mem_write_ea(addr, 2, aq & rl, rl, true), + (WORD, _) => mem_write_ea(addr, 4, aq & rl, rl, true), + (DOUBLE, 64) => mem_write_ea(addr, 8, aq & rl, rl, true), + _ => internal_error(__FILE__, __LINE__, "Unexpected AMOCAS width") + }; + let rs2_val : xlenbits = match width { + BYTE => sign_extend(X(rs2)[7..0]), + HALF => sign_extend(X(rs2)[15..0]), + WORD => sign_extend(X(rs2)[31..0]), + DOUBLE => X(rs2) + }; + let rd_val : xlenbits = match width { + BYTE => sign_extend(X(rd)[7..0]), + HALF => sign_extend(X(rd)[15..0]), + WORD => sign_extend(X(rd)[31..0]), + DOUBLE => X(rd) + }; + match (eares) { + MemException(e) => { handle_mem_exception(vaddr, e); RETIRE_FAIL }, + MemValue(_) => { + let mval : MemoryOpResult(xlenbits) = match (width, sizeof(xlen)) { + (BYTE, _) => extend_value(false, mem_read(ReadWrite(Data, Data), addr, 1, aq, aq & rl, true)), + (HALF, _) => extend_value(false, mem_read(ReadWrite(Data, Data), addr, 2, aq, aq & rl, true)), + (WORD, _) => extend_value(false, mem_read(ReadWrite(Data, Data), addr, 4, aq, aq & rl, true)), + (DOUBLE, 64) => extend_value(false, mem_read(ReadWrite(Data, Data), addr, 8, aq, aq & rl, true)), + _ => internal_error(__FILE__, __LINE__, "Unexpected AMOCAS width") + }; + match (mval) { + MemException(e) => { handle_mem_exception(vaddr, e); RETIRE_FAIL }, + MemValue(loaded) => { + let success : bool = (loaded == rs2_val); + let result : xlenbits = if success then rd_val else loaded; + let rval : xlenbits = match width { + BYTE => sign_extend(loaded[7..0]), + HALF => sign_extend(loaded[15..0]), + WORD => sign_extend(loaded[31..0]), + DOUBLE => loaded + }; + let wval : MemoryOpResult(bool) = if success then { + match (width, sizeof(xlen)) { + (BYTE, _) => mem_write_value(addr, 1, result[7..0], aq & rl, rl, true), + (HALF, _) => mem_write_value(addr, 2, result[15..0], aq & rl, rl, true), + (WORD, _) => mem_write_value(addr, 4, result[31..0], aq & rl, rl, true), + (DOUBLE, 64) => mem_write_value(addr, 8, result, aq & rl, rl, true), + _ => internal_error(__FILE__, __LINE__, "Unexpected AMOCAS width") + } + } else { + MemValue(true) /* No write on compare failure */ + }; + match (wval) { + MemValue(true) => { X(rd) = rval; RETIRE_SUCCESS }, + MemValue(false) => { internal_error(__FILE__, __LINE__, "AMOCAS got false from mem_write_value") }, + MemException(e) => { handle_mem_exception(vaddr, e); RETIRE_FAIL } + } + } + } + } + } + } + } + } + } + } else { + handle_illegal(); + RETIRE_FAIL + } + } + +# SPDX-SnippetEnd diff --git a/spec/std/isa/inst/Zacas/amocas.d.aqrl.yaml b/spec/std/isa/inst/Zacas/amocas.d.aqrl.yaml new file mode 100644 index 0000000000..d4e5328860 --- /dev/null +++ b/spec/std/isa/inst/Zacas/amocas.d.aqrl.yaml @@ -0,0 +1,134 @@ +# Copyright (c) Qualcomm Technologies, Inc. and/or its subsidiaries. + +# WARNING: This file is auto-generated from spec/std/isa/inst/Zacas/amocas.SIZE.AQRL.layout# Copyright (c) Abhijit Das(Sukuna0007Abhi) +# SPDX-License-Identifier: BSD-3-Clause-Clear + +# yaml-language-server: $schema=../../../../schemas/inst_schema.json + +$schema: "inst_schema.json#" +kind: instruction +name: amocas.d.aqrl +long_name: Atomic compare-and-swap doubleword (acquire-release) +description: | + Atomically with acquire and release ordering: + + * Load the doubleword at address _xs1_ + * Write the loaded value into _xd_ + * Compare the loaded value with the value of register _xs2_ + * If equal, write the value of register _xs2+1_ to the address in _xs1_ +definedBy: Zacas +base: 64 +assembly: xd, xs2, (xs1) +encoding: + match: 0010111----------011-----0101111 + variables: + - name: xs2 + location: 24-20 + - name: xs1 + location: 19-15 + - name: xd + location: 11-7 +access: + s: always + u: always + vs: always + vu: always +operation(): | + if (!implemented?(ExtensionName::Zacas)) { + raise (ExceptionCode::IllegalInstruction, mode(), $encoding); + } + + memory_model_acquire(); + + XReg virtual_address = X[xs1]; + # TODO + # X[xd] = amocas64(virtual_address, X[xs2], X[xd], 1'b1, 1'b1, $encoding); + + memory_model_release(); + +# SPDX-SnippetBegin +# SPDX-FileCopyrightText: 2017-2025 Contributors to the RISCV Sail Model +# SPDX-License-Identifier: BSD-2-Clause +sail(): | + { + if extension("Zacas") then { + /* Get the address, X(rs1) (no offset). + * Some extensions perform additional checks on address validity. + */ + match ext_data_get_addr(rs1, zeros(), ReadWrite(Data, Data), width) { + Ext_DataAddr_Error(e) => { ext_handle_data_check_error(e); RETIRE_FAIL }, + Ext_DataAddr_OK(vaddr) => { + match translateAddr(vaddr, ReadWrite(Data, Data)) { + TR_Failure(e, _) => { handle_mem_exception(vaddr, e); RETIRE_FAIL }, + TR_Address(addr, _) => { + let eares : MemoryOpResult(unit) = match (width, sizeof(xlen)) { + (BYTE, _) => mem_write_ea(addr, 1, aq & rl, rl, true), + (HALF, _) => mem_write_ea(addr, 2, aq & rl, rl, true), + (WORD, _) => mem_write_ea(addr, 4, aq & rl, rl, true), + (DOUBLE, 64) => mem_write_ea(addr, 8, aq & rl, rl, true), + _ => internal_error(__FILE__, __LINE__, "Unexpected AMOCAS width") + }; + let rs2_val : xlenbits = match width { + BYTE => sign_extend(X(rs2)[7..0]), + HALF => sign_extend(X(rs2)[15..0]), + WORD => sign_extend(X(rs2)[31..0]), + DOUBLE => X(rs2) + }; + let rd_val : xlenbits = match width { + BYTE => sign_extend(X(rd)[7..0]), + HALF => sign_extend(X(rd)[15..0]), + WORD => sign_extend(X(rd)[31..0]), + DOUBLE => X(rd) + }; + match (eares) { + MemException(e) => { handle_mem_exception(vaddr, e); RETIRE_FAIL }, + MemValue(_) => { + let mval : MemoryOpResult(xlenbits) = match (width, sizeof(xlen)) { + (BYTE, _) => extend_value(false, mem_read(ReadWrite(Data, Data), addr, 1, aq, aq & rl, true)), + (HALF, _) => extend_value(false, mem_read(ReadWrite(Data, Data), addr, 2, aq, aq & rl, true)), + (WORD, _) => extend_value(false, mem_read(ReadWrite(Data, Data), addr, 4, aq, aq & rl, true)), + (DOUBLE, 64) => extend_value(false, mem_read(ReadWrite(Data, Data), addr, 8, aq, aq & rl, true)), + _ => internal_error(__FILE__, __LINE__, "Unexpected AMOCAS width") + }; + match (mval) { + MemException(e) => { handle_mem_exception(vaddr, e); RETIRE_FAIL }, + MemValue(loaded) => { + let success : bool = (loaded == rs2_val); + let result : xlenbits = if success then rd_val else loaded; + let rval : xlenbits = match width { + BYTE => sign_extend(loaded[7..0]), + HALF => sign_extend(loaded[15..0]), + WORD => sign_extend(loaded[31..0]), + DOUBLE => loaded + }; + let wval : MemoryOpResult(bool) = if success then { + match (width, sizeof(xlen)) { + (BYTE, _) => mem_write_value(addr, 1, result[7..0], aq & rl, rl, true), + (HALF, _) => mem_write_value(addr, 2, result[15..0], aq & rl, rl, true), + (WORD, _) => mem_write_value(addr, 4, result[31..0], aq & rl, rl, true), + (DOUBLE, 64) => mem_write_value(addr, 8, result, aq & rl, rl, true), + _ => internal_error(__FILE__, __LINE__, "Unexpected AMOCAS width") + } + } else { + MemValue(true) /* No write on compare failure */ + }; + match (wval) { + MemValue(true) => { X(rd) = rval; RETIRE_SUCCESS }, + MemValue(false) => { internal_error(__FILE__, __LINE__, "AMOCAS got false from mem_write_value") }, + MemException(e) => { handle_mem_exception(vaddr, e); RETIRE_FAIL } + } + } + } + } + } + } + } + } + } + } else { + handle_illegal(); + RETIRE_FAIL + } + } + +# SPDX-SnippetEnd diff --git a/spec/std/isa/inst/Zacas/amocas.d.rl.yaml b/spec/std/isa/inst/Zacas/amocas.d.rl.yaml new file mode 100644 index 0000000000..f2713dfe08 --- /dev/null +++ b/spec/std/isa/inst/Zacas/amocas.d.rl.yaml @@ -0,0 +1,132 @@ +# Copyright (c) Qualcomm Technologies, Inc. and/or its subsidiaries. + +# WARNING: This file is auto-generated from spec/std/isa/inst/Zacas/amocas.SIZE.AQRL.layout# Copyright (c) Abhijit Das(Sukuna0007Abhi) +# SPDX-License-Identifier: BSD-3-Clause-Clear + +# yaml-language-server: $schema=../../../../schemas/inst_schema.json + +$schema: "inst_schema.json#" +kind: instruction +name: amocas.d.rl +long_name: Atomic compare-and-swap doubleword (release) +description: | + Atomically with release ordering: + + * Load the doubleword at address _xs1_ + * Write the loaded value into _xd_ + * Compare the loaded value with the value of register _xs2_ + * If equal, write the value of register _xs2+1_ to the address in _xs1_ +definedBy: Zacas +base: 64 +assembly: xd, xs2, (xs1) +encoding: + match: 0010101----------011-----0101111 + variables: + - name: xs2 + location: 24-20 + - name: xs1 + location: 19-15 + - name: xd + location: 11-7 +access: + s: always + u: always + vs: always + vu: always +operation(): | + if (!implemented?(ExtensionName::Zacas)) { + raise (ExceptionCode::IllegalInstruction, mode(), $encoding); + } + + XReg virtual_address = X[xs1]; + # TODO + # X[xd] = amocas64(virtual_address, X[xs2], X[xd], 1'b0, 1'b1, $encoding); + + memory_model_release(); + +# SPDX-SnippetBegin +# SPDX-FileCopyrightText: 2017-2025 Contributors to the RISCV Sail Model +# SPDX-License-Identifier: BSD-2-Clause +sail(): | + { + if extension("Zacas") then { + /* Get the address, X(rs1) (no offset). + * Some extensions perform additional checks on address validity. + */ + match ext_data_get_addr(rs1, zeros(), ReadWrite(Data, Data), width) { + Ext_DataAddr_Error(e) => { ext_handle_data_check_error(e); RETIRE_FAIL }, + Ext_DataAddr_OK(vaddr) => { + match translateAddr(vaddr, ReadWrite(Data, Data)) { + TR_Failure(e, _) => { handle_mem_exception(vaddr, e); RETIRE_FAIL }, + TR_Address(addr, _) => { + let eares : MemoryOpResult(unit) = match (width, sizeof(xlen)) { + (BYTE, _) => mem_write_ea(addr, 1, aq & rl, rl, true), + (HALF, _) => mem_write_ea(addr, 2, aq & rl, rl, true), + (WORD, _) => mem_write_ea(addr, 4, aq & rl, rl, true), + (DOUBLE, 64) => mem_write_ea(addr, 8, aq & rl, rl, true), + _ => internal_error(__FILE__, __LINE__, "Unexpected AMOCAS width") + }; + let rs2_val : xlenbits = match width { + BYTE => sign_extend(X(rs2)[7..0]), + HALF => sign_extend(X(rs2)[15..0]), + WORD => sign_extend(X(rs2)[31..0]), + DOUBLE => X(rs2) + }; + let rd_val : xlenbits = match width { + BYTE => sign_extend(X(rd)[7..0]), + HALF => sign_extend(X(rd)[15..0]), + WORD => sign_extend(X(rd)[31..0]), + DOUBLE => X(rd) + }; + match (eares) { + MemException(e) => { handle_mem_exception(vaddr, e); RETIRE_FAIL }, + MemValue(_) => { + let mval : MemoryOpResult(xlenbits) = match (width, sizeof(xlen)) { + (BYTE, _) => extend_value(false, mem_read(ReadWrite(Data, Data), addr, 1, aq, aq & rl, true)), + (HALF, _) => extend_value(false, mem_read(ReadWrite(Data, Data), addr, 2, aq, aq & rl, true)), + (WORD, _) => extend_value(false, mem_read(ReadWrite(Data, Data), addr, 4, aq, aq & rl, true)), + (DOUBLE, 64) => extend_value(false, mem_read(ReadWrite(Data, Data), addr, 8, aq, aq & rl, true)), + _ => internal_error(__FILE__, __LINE__, "Unexpected AMOCAS width") + }; + match (mval) { + MemException(e) => { handle_mem_exception(vaddr, e); RETIRE_FAIL }, + MemValue(loaded) => { + let success : bool = (loaded == rs2_val); + let result : xlenbits = if success then rd_val else loaded; + let rval : xlenbits = match width { + BYTE => sign_extend(loaded[7..0]), + HALF => sign_extend(loaded[15..0]), + WORD => sign_extend(loaded[31..0]), + DOUBLE => loaded + }; + let wval : MemoryOpResult(bool) = if success then { + match (width, sizeof(xlen)) { + (BYTE, _) => mem_write_value(addr, 1, result[7..0], aq & rl, rl, true), + (HALF, _) => mem_write_value(addr, 2, result[15..0], aq & rl, rl, true), + (WORD, _) => mem_write_value(addr, 4, result[31..0], aq & rl, rl, true), + (DOUBLE, 64) => mem_write_value(addr, 8, result, aq & rl, rl, true), + _ => internal_error(__FILE__, __LINE__, "Unexpected AMOCAS width") + } + } else { + MemValue(true) /* No write on compare failure */ + }; + match (wval) { + MemValue(true) => { X(rd) = rval; RETIRE_SUCCESS }, + MemValue(false) => { internal_error(__FILE__, __LINE__, "AMOCAS got false from mem_write_value") }, + MemException(e) => { handle_mem_exception(vaddr, e); RETIRE_FAIL } + } + } + } + } + } + } + } + } + } + } else { + handle_illegal(); + RETIRE_FAIL + } + } + +# SPDX-SnippetEnd diff --git a/spec/std/isa/inst/Zacas/amocas.d.yaml b/spec/std/isa/inst/Zacas/amocas.d.yaml index c410c921c4..c120a1e265 100644 --- a/spec/std/isa/inst/Zacas/amocas.d.yaml +++ b/spec/std/isa/inst/Zacas/amocas.d.yaml @@ -1,89 +1,130 @@ # Copyright (c) Qualcomm Technologies, Inc. and/or its subsidiaries. + +# WARNING: This file is auto-generated from spec/std/isa/inst/Zacas/amocas.SIZE.AQRL.layout# Copyright (c) Abhijit Das(Sukuna0007Abhi) # SPDX-License-Identifier: BSD-3-Clause-Clear ---- # yaml-language-server: $schema=../../../../schemas/inst_schema.json $schema: "inst_schema.json#" kind: instruction name: amocas.d -long_name: Atomic Compare-and-Swap Doubleword +long_name: Atomic compare-and-swap doubleword description: | - For RV32, AMOCAS.D atomically loads 64-bits of a data value from address in - xs1, compares the loaded value to a 64-bit value held in a register pair - consisting of xd and xd+1, and if the comparison is bitwise equal, then - stores the 64-bit value held in the register pair xs2 and xs2+1 to the - original address in xs1. The value loaded from memory is placed into the - register pair xd and xd+1. The instruction requires the first register in - the pair to be even numbered; encodings with odd-numbered registers - specified in xs2 and xd are reserved. When the first register of a source - register pair is x0, then both halves of the pair read as zero. When the - first register of a destination register pair is x0, then the entire - register result is discarded and neither destination register is written. - - For RV64, AMOCAS.D atomically loads 64-bits of a data value from address in - xs1, compares the loaded value to a 64-bit value held in xd, and if the - comparison is bitwise equal, then stores the 64-bit value held in xs2 to the - original address in xs1. The value loaded from memory is placed into - register xd. - - Just as for AMOs in the A extension, AMOCAS.D requires that the address held - in xs1 be naturally aligned to the size of the operand (i.e., eight-byte - aligned for doublewords). And the same exception options apply if the - address is not naturally aligned. - - Just as for AMOs in the A extension, the AMOCAS.D optionally provides release - consistency semantics, using the aq and rl bits, to help implement - multiprocessor synchronization. The memory operation performed by an - AMOCAS.D, when successful, has acquire semantics if aq bit is 1 and has - release semantics if rl bit is 1. The memory operation performed by an - AMOCAS.W/D/Q, when not successful, has acquire semantics if aq bit is 1 but - does not have release semantics, regardless of rl. - - A FENCE instruction may be used to order the memory read access and, if - produced, the memory write access by an AMOCAS.D instruction. - - [Note] An unsuccessful AMOCAS.D may either not perform a memory write or may - write back the old value loaded from memory. The memory write, if produced, - does not have release semantics, regardless of rl. - - An AMOCAS.D instruction always requires write permissions. + Atomically: + * Load the doubleword at address _xs1_ + * Write the loaded value into _xd_ + * Compare the loaded value with the value of register _xs2_ + * If equal, write the value of register _xs2+1_ to the address in _xs1_ definedBy: Zacas +base: 64 assembly: xd, xs2, (xs1) encoding: - RV32: - match: 00101------------011-----0101111 - variables: - - name: aq - location: 26-26 - - name: rl - location: 25-25 - - name: xs2 - location: 24-20 - not: [1, 3, 5, 7, 9, 11, 13, 15, 17, 19, 21, 23, 25, 27, 29, 31] - - name: xs1 - location: 19-15 - - name: xd - location: 11-7 - not: [1, 3, 5, 7, 9, 11, 13, 15, 17, 19, 21, 23, 25, 27, 29, 31] - RV64: - match: 00101------------011-----0101111 - variables: - - name: aq - location: 26-26 - - name: rl - location: 25-25 - - name: xs2 - location: 24-20 - - name: xs1 - location: 19-15 - - name: xd - location: 11-7 + match: 0010100----------011-----0101111 + variables: + - name: xs2 + location: 24-20 + - name: xs1 + location: 19-15 + - name: xd + location: 11-7 access: s: always u: always vs: always vu: always -data_independent_timing: false operation(): | + if (!implemented?(ExtensionName::Zacas)) { + raise (ExceptionCode::IllegalInstruction, mode(), $encoding); + } + + XReg virtual_address = X[xs1]; + # TODO + # X[xd] = amocas64(virtual_address, X[xs2], X[xd], 1'b0, 1'b0, $encoding); + +# SPDX-SnippetBegin +# SPDX-FileCopyrightText: 2017-2025 Contributors to the RISCV Sail Model +# SPDX-License-Identifier: BSD-2-Clause +sail(): | + { + if extension("Zacas") then { + /* Get the address, X(rs1) (no offset). + * Some extensions perform additional checks on address validity. + */ + match ext_data_get_addr(rs1, zeros(), ReadWrite(Data, Data), width) { + Ext_DataAddr_Error(e) => { ext_handle_data_check_error(e); RETIRE_FAIL }, + Ext_DataAddr_OK(vaddr) => { + match translateAddr(vaddr, ReadWrite(Data, Data)) { + TR_Failure(e, _) => { handle_mem_exception(vaddr, e); RETIRE_FAIL }, + TR_Address(addr, _) => { + let eares : MemoryOpResult(unit) = match (width, sizeof(xlen)) { + (BYTE, _) => mem_write_ea(addr, 1, aq & rl, rl, true), + (HALF, _) => mem_write_ea(addr, 2, aq & rl, rl, true), + (WORD, _) => mem_write_ea(addr, 4, aq & rl, rl, true), + (DOUBLE, 64) => mem_write_ea(addr, 8, aq & rl, rl, true), + _ => internal_error(__FILE__, __LINE__, "Unexpected AMOCAS width") + }; + let rs2_val : xlenbits = match width { + BYTE => sign_extend(X(rs2)[7..0]), + HALF => sign_extend(X(rs2)[15..0]), + WORD => sign_extend(X(rs2)[31..0]), + DOUBLE => X(rs2) + }; + let rd_val : xlenbits = match width { + BYTE => sign_extend(X(rd)[7..0]), + HALF => sign_extend(X(rd)[15..0]), + WORD => sign_extend(X(rd)[31..0]), + DOUBLE => X(rd) + }; + match (eares) { + MemException(e) => { handle_mem_exception(vaddr, e); RETIRE_FAIL }, + MemValue(_) => { + let mval : MemoryOpResult(xlenbits) = match (width, sizeof(xlen)) { + (BYTE, _) => extend_value(false, mem_read(ReadWrite(Data, Data), addr, 1, aq, aq & rl, true)), + (HALF, _) => extend_value(false, mem_read(ReadWrite(Data, Data), addr, 2, aq, aq & rl, true)), + (WORD, _) => extend_value(false, mem_read(ReadWrite(Data, Data), addr, 4, aq, aq & rl, true)), + (DOUBLE, 64) => extend_value(false, mem_read(ReadWrite(Data, Data), addr, 8, aq, aq & rl, true)), + _ => internal_error(__FILE__, __LINE__, "Unexpected AMOCAS width") + }; + match (mval) { + MemException(e) => { handle_mem_exception(vaddr, e); RETIRE_FAIL }, + MemValue(loaded) => { + let success : bool = (loaded == rs2_val); + let result : xlenbits = if success then rd_val else loaded; + let rval : xlenbits = match width { + BYTE => sign_extend(loaded[7..0]), + HALF => sign_extend(loaded[15..0]), + WORD => sign_extend(loaded[31..0]), + DOUBLE => loaded + }; + let wval : MemoryOpResult(bool) = if success then { + match (width, sizeof(xlen)) { + (BYTE, _) => mem_write_value(addr, 1, result[7..0], aq & rl, rl, true), + (HALF, _) => mem_write_value(addr, 2, result[15..0], aq & rl, rl, true), + (WORD, _) => mem_write_value(addr, 4, result[31..0], aq & rl, rl, true), + (DOUBLE, 64) => mem_write_value(addr, 8, result, aq & rl, rl, true), + _ => internal_error(__FILE__, __LINE__, "Unexpected AMOCAS width") + } + } else { + MemValue(true) /* No write on compare failure */ + }; + match (wval) { + MemValue(true) => { X(rd) = rval; RETIRE_SUCCESS }, + MemValue(false) => { internal_error(__FILE__, __LINE__, "AMOCAS got false from mem_write_value") }, + MemException(e) => { handle_mem_exception(vaddr, e); RETIRE_FAIL } + } + } + } + } + } + } + } + } + } + } else { + handle_illegal(); + RETIRE_FAIL + } + } + +# SPDX-SnippetEnd diff --git a/spec/std/isa/inst/Zacas/amocas.q.aq.yaml b/spec/std/isa/inst/Zacas/amocas.q.aq.yaml new file mode 100644 index 0000000000..8f00ca1549 --- /dev/null +++ b/spec/std/isa/inst/Zacas/amocas.q.aq.yaml @@ -0,0 +1,132 @@ +# Copyright (c) Qualcomm Technologies, Inc. and/or its subsidiaries. + +# WARNING: This file is auto-generated from spec/std/isa/inst/Zacas/amocas.SIZE.AQRL.layout# Copyright (c) Abhijit Das(Sukuna0007Abhi) +# SPDX-License-Identifier: BSD-3-Clause-Clear + +# yaml-language-server: $schema=../../../../schemas/inst_schema.json + +$schema: "inst_schema.json#" +kind: instruction +name: amocas.q.aq +long_name: Atomic compare-and-swap quadword (acquire) +description: | + Atomically with acquire ordering: + + * Load the quadword at address _xs1_ + * Write the loaded value into _xd_ + * Compare the loaded value with the value of register _xs2_ + * If equal, write the value of register _xs2+1_ to the address in _xs1_ +definedBy: Zacas +base: 64 +assembly: xd, xs2, (xs1) +encoding: + match: 0010110----------100-----0101111 + variables: + - name: xs2 + location: 24-20 + - name: xs1 + location: 19-15 + - name: xd + location: 11-7 +access: + s: always + u: always + vs: always + vu: always +operation(): | + if (!implemented?(ExtensionName::Zacas)) { + raise (ExceptionCode::IllegalInstruction, mode(), $encoding); + } + + memory_model_acquire(); + + XReg virtual_address = X[xs1]; + # TODO + # X[xd] = amocas128(virtual_address, X[xs2], X[xd], 1'b1, 1'b0, $encoding); + +# SPDX-SnippetBegin +# SPDX-FileCopyrightText: 2017-2025 Contributors to the RISCV Sail Model +# SPDX-License-Identifier: BSD-2-Clause +sail(): | + { + if extension("Zacas") then { + /* Get the address, X(rs1) (no offset). + * Some extensions perform additional checks on address validity. + */ + match ext_data_get_addr(rs1, zeros(), ReadWrite(Data, Data), width) { + Ext_DataAddr_Error(e) => { ext_handle_data_check_error(e); RETIRE_FAIL }, + Ext_DataAddr_OK(vaddr) => { + match translateAddr(vaddr, ReadWrite(Data, Data)) { + TR_Failure(e, _) => { handle_mem_exception(vaddr, e); RETIRE_FAIL }, + TR_Address(addr, _) => { + let eares : MemoryOpResult(unit) = match (width, sizeof(xlen)) { + (BYTE, _) => mem_write_ea(addr, 1, aq & rl, rl, true), + (HALF, _) => mem_write_ea(addr, 2, aq & rl, rl, true), + (WORD, _) => mem_write_ea(addr, 4, aq & rl, rl, true), + (DOUBLE, 64) => mem_write_ea(addr, 8, aq & rl, rl, true), + _ => internal_error(__FILE__, __LINE__, "Unexpected AMOCAS width") + }; + let rs2_val : xlenbits = match width { + BYTE => sign_extend(X(rs2)[7..0]), + HALF => sign_extend(X(rs2)[15..0]), + WORD => sign_extend(X(rs2)[31..0]), + DOUBLE => X(rs2) + }; + let rd_val : xlenbits = match width { + BYTE => sign_extend(X(rd)[7..0]), + HALF => sign_extend(X(rd)[15..0]), + WORD => sign_extend(X(rd)[31..0]), + DOUBLE => X(rd) + }; + match (eares) { + MemException(e) => { handle_mem_exception(vaddr, e); RETIRE_FAIL }, + MemValue(_) => { + let mval : MemoryOpResult(xlenbits) = match (width, sizeof(xlen)) { + (BYTE, _) => extend_value(false, mem_read(ReadWrite(Data, Data), addr, 1, aq, aq & rl, true)), + (HALF, _) => extend_value(false, mem_read(ReadWrite(Data, Data), addr, 2, aq, aq & rl, true)), + (WORD, _) => extend_value(false, mem_read(ReadWrite(Data, Data), addr, 4, aq, aq & rl, true)), + (DOUBLE, 64) => extend_value(false, mem_read(ReadWrite(Data, Data), addr, 8, aq, aq & rl, true)), + _ => internal_error(__FILE__, __LINE__, "Unexpected AMOCAS width") + }; + match (mval) { + MemException(e) => { handle_mem_exception(vaddr, e); RETIRE_FAIL }, + MemValue(loaded) => { + let success : bool = (loaded == rs2_val); + let result : xlenbits = if success then rd_val else loaded; + let rval : xlenbits = match width { + BYTE => sign_extend(loaded[7..0]), + HALF => sign_extend(loaded[15..0]), + WORD => sign_extend(loaded[31..0]), + DOUBLE => loaded + }; + let wval : MemoryOpResult(bool) = if success then { + match (width, sizeof(xlen)) { + (BYTE, _) => mem_write_value(addr, 1, result[7..0], aq & rl, rl, true), + (HALF, _) => mem_write_value(addr, 2, result[15..0], aq & rl, rl, true), + (WORD, _) => mem_write_value(addr, 4, result[31..0], aq & rl, rl, true), + (DOUBLE, 64) => mem_write_value(addr, 8, result, aq & rl, rl, true), + _ => internal_error(__FILE__, __LINE__, "Unexpected AMOCAS width") + } + } else { + MemValue(true) /* No write on compare failure */ + }; + match (wval) { + MemValue(true) => { X(rd) = rval; RETIRE_SUCCESS }, + MemValue(false) => { internal_error(__FILE__, __LINE__, "AMOCAS got false from mem_write_value") }, + MemException(e) => { handle_mem_exception(vaddr, e); RETIRE_FAIL } + } + } + } + } + } + } + } + } + } + } else { + handle_illegal(); + RETIRE_FAIL + } + } + +# SPDX-SnippetEnd diff --git a/spec/std/isa/inst/Zacas/amocas.q.aqrl.yaml b/spec/std/isa/inst/Zacas/amocas.q.aqrl.yaml new file mode 100644 index 0000000000..d1aa216d98 --- /dev/null +++ b/spec/std/isa/inst/Zacas/amocas.q.aqrl.yaml @@ -0,0 +1,134 @@ +# Copyright (c) Qualcomm Technologies, Inc. and/or its subsidiaries. + +# WARNING: This file is auto-generated from spec/std/isa/inst/Zacas/amocas.SIZE.AQRL.layout# Copyright (c) Abhijit Das(Sukuna0007Abhi) +# SPDX-License-Identifier: BSD-3-Clause-Clear + +# yaml-language-server: $schema=../../../../schemas/inst_schema.json + +$schema: "inst_schema.json#" +kind: instruction +name: amocas.q.aqrl +long_name: Atomic compare-and-swap quadword (acquire-release) +description: | + Atomically with acquire and release ordering: + + * Load the quadword at address _xs1_ + * Write the loaded value into _xd_ + * Compare the loaded value with the value of register _xs2_ + * If equal, write the value of register _xs2+1_ to the address in _xs1_ +definedBy: Zacas +base: 64 +assembly: xd, xs2, (xs1) +encoding: + match: 0010111----------100-----0101111 + variables: + - name: xs2 + location: 24-20 + - name: xs1 + location: 19-15 + - name: xd + location: 11-7 +access: + s: always + u: always + vs: always + vu: always +operation(): | + if (!implemented?(ExtensionName::Zacas)) { + raise (ExceptionCode::IllegalInstruction, mode(), $encoding); + } + + memory_model_acquire(); + + XReg virtual_address = X[xs1]; + # TODO + # X[xd] = amocas128(virtual_address, X[xs2], X[xd], 1'b1, 1'b1, $encoding); + + memory_model_release(); + +# SPDX-SnippetBegin +# SPDX-FileCopyrightText: 2017-2025 Contributors to the RISCV Sail Model +# SPDX-License-Identifier: BSD-2-Clause +sail(): | + { + if extension("Zacas") then { + /* Get the address, X(rs1) (no offset). + * Some extensions perform additional checks on address validity. + */ + match ext_data_get_addr(rs1, zeros(), ReadWrite(Data, Data), width) { + Ext_DataAddr_Error(e) => { ext_handle_data_check_error(e); RETIRE_FAIL }, + Ext_DataAddr_OK(vaddr) => { + match translateAddr(vaddr, ReadWrite(Data, Data)) { + TR_Failure(e, _) => { handle_mem_exception(vaddr, e); RETIRE_FAIL }, + TR_Address(addr, _) => { + let eares : MemoryOpResult(unit) = match (width, sizeof(xlen)) { + (BYTE, _) => mem_write_ea(addr, 1, aq & rl, rl, true), + (HALF, _) => mem_write_ea(addr, 2, aq & rl, rl, true), + (WORD, _) => mem_write_ea(addr, 4, aq & rl, rl, true), + (DOUBLE, 64) => mem_write_ea(addr, 8, aq & rl, rl, true), + _ => internal_error(__FILE__, __LINE__, "Unexpected AMOCAS width") + }; + let rs2_val : xlenbits = match width { + BYTE => sign_extend(X(rs2)[7..0]), + HALF => sign_extend(X(rs2)[15..0]), + WORD => sign_extend(X(rs2)[31..0]), + DOUBLE => X(rs2) + }; + let rd_val : xlenbits = match width { + BYTE => sign_extend(X(rd)[7..0]), + HALF => sign_extend(X(rd)[15..0]), + WORD => sign_extend(X(rd)[31..0]), + DOUBLE => X(rd) + }; + match (eares) { + MemException(e) => { handle_mem_exception(vaddr, e); RETIRE_FAIL }, + MemValue(_) => { + let mval : MemoryOpResult(xlenbits) = match (width, sizeof(xlen)) { + (BYTE, _) => extend_value(false, mem_read(ReadWrite(Data, Data), addr, 1, aq, aq & rl, true)), + (HALF, _) => extend_value(false, mem_read(ReadWrite(Data, Data), addr, 2, aq, aq & rl, true)), + (WORD, _) => extend_value(false, mem_read(ReadWrite(Data, Data), addr, 4, aq, aq & rl, true)), + (DOUBLE, 64) => extend_value(false, mem_read(ReadWrite(Data, Data), addr, 8, aq, aq & rl, true)), + _ => internal_error(__FILE__, __LINE__, "Unexpected AMOCAS width") + }; + match (mval) { + MemException(e) => { handle_mem_exception(vaddr, e); RETIRE_FAIL }, + MemValue(loaded) => { + let success : bool = (loaded == rs2_val); + let result : xlenbits = if success then rd_val else loaded; + let rval : xlenbits = match width { + BYTE => sign_extend(loaded[7..0]), + HALF => sign_extend(loaded[15..0]), + WORD => sign_extend(loaded[31..0]), + DOUBLE => loaded + }; + let wval : MemoryOpResult(bool) = if success then { + match (width, sizeof(xlen)) { + (BYTE, _) => mem_write_value(addr, 1, result[7..0], aq & rl, rl, true), + (HALF, _) => mem_write_value(addr, 2, result[15..0], aq & rl, rl, true), + (WORD, _) => mem_write_value(addr, 4, result[31..0], aq & rl, rl, true), + (DOUBLE, 64) => mem_write_value(addr, 8, result, aq & rl, rl, true), + _ => internal_error(__FILE__, __LINE__, "Unexpected AMOCAS width") + } + } else { + MemValue(true) /* No write on compare failure */ + }; + match (wval) { + MemValue(true) => { X(rd) = rval; RETIRE_SUCCESS }, + MemValue(false) => { internal_error(__FILE__, __LINE__, "AMOCAS got false from mem_write_value") }, + MemException(e) => { handle_mem_exception(vaddr, e); RETIRE_FAIL } + } + } + } + } + } + } + } + } + } + } else { + handle_illegal(); + RETIRE_FAIL + } + } + +# SPDX-SnippetEnd diff --git a/spec/std/isa/inst/Zacas/amocas.q.rl.yaml b/spec/std/isa/inst/Zacas/amocas.q.rl.yaml new file mode 100644 index 0000000000..dea9e7c55a --- /dev/null +++ b/spec/std/isa/inst/Zacas/amocas.q.rl.yaml @@ -0,0 +1,132 @@ +# Copyright (c) Qualcomm Technologies, Inc. and/or its subsidiaries. + +# WARNING: This file is auto-generated from spec/std/isa/inst/Zacas/amocas.SIZE.AQRL.layout# Copyright (c) Abhijit Das(Sukuna0007Abhi) +# SPDX-License-Identifier: BSD-3-Clause-Clear + +# yaml-language-server: $schema=../../../../schemas/inst_schema.json + +$schema: "inst_schema.json#" +kind: instruction +name: amocas.q.rl +long_name: Atomic compare-and-swap quadword (release) +description: | + Atomically with release ordering: + + * Load the quadword at address _xs1_ + * Write the loaded value into _xd_ + * Compare the loaded value with the value of register _xs2_ + * If equal, write the value of register _xs2+1_ to the address in _xs1_ +definedBy: Zacas +base: 64 +assembly: xd, xs2, (xs1) +encoding: + match: 0010101----------100-----0101111 + variables: + - name: xs2 + location: 24-20 + - name: xs1 + location: 19-15 + - name: xd + location: 11-7 +access: + s: always + u: always + vs: always + vu: always +operation(): | + if (!implemented?(ExtensionName::Zacas)) { + raise (ExceptionCode::IllegalInstruction, mode(), $encoding); + } + + XReg virtual_address = X[xs1]; + # TODO + # X[xd] = amocas128(virtual_address, X[xs2], X[xd], 1'b0, 1'b1, $encoding); + + memory_model_release(); + +# SPDX-SnippetBegin +# SPDX-FileCopyrightText: 2017-2025 Contributors to the RISCV Sail Model +# SPDX-License-Identifier: BSD-2-Clause +sail(): | + { + if extension("Zacas") then { + /* Get the address, X(rs1) (no offset). + * Some extensions perform additional checks on address validity. + */ + match ext_data_get_addr(rs1, zeros(), ReadWrite(Data, Data), width) { + Ext_DataAddr_Error(e) => { ext_handle_data_check_error(e); RETIRE_FAIL }, + Ext_DataAddr_OK(vaddr) => { + match translateAddr(vaddr, ReadWrite(Data, Data)) { + TR_Failure(e, _) => { handle_mem_exception(vaddr, e); RETIRE_FAIL }, + TR_Address(addr, _) => { + let eares : MemoryOpResult(unit) = match (width, sizeof(xlen)) { + (BYTE, _) => mem_write_ea(addr, 1, aq & rl, rl, true), + (HALF, _) => mem_write_ea(addr, 2, aq & rl, rl, true), + (WORD, _) => mem_write_ea(addr, 4, aq & rl, rl, true), + (DOUBLE, 64) => mem_write_ea(addr, 8, aq & rl, rl, true), + _ => internal_error(__FILE__, __LINE__, "Unexpected AMOCAS width") + }; + let rs2_val : xlenbits = match width { + BYTE => sign_extend(X(rs2)[7..0]), + HALF => sign_extend(X(rs2)[15..0]), + WORD => sign_extend(X(rs2)[31..0]), + DOUBLE => X(rs2) + }; + let rd_val : xlenbits = match width { + BYTE => sign_extend(X(rd)[7..0]), + HALF => sign_extend(X(rd)[15..0]), + WORD => sign_extend(X(rd)[31..0]), + DOUBLE => X(rd) + }; + match (eares) { + MemException(e) => { handle_mem_exception(vaddr, e); RETIRE_FAIL }, + MemValue(_) => { + let mval : MemoryOpResult(xlenbits) = match (width, sizeof(xlen)) { + (BYTE, _) => extend_value(false, mem_read(ReadWrite(Data, Data), addr, 1, aq, aq & rl, true)), + (HALF, _) => extend_value(false, mem_read(ReadWrite(Data, Data), addr, 2, aq, aq & rl, true)), + (WORD, _) => extend_value(false, mem_read(ReadWrite(Data, Data), addr, 4, aq, aq & rl, true)), + (DOUBLE, 64) => extend_value(false, mem_read(ReadWrite(Data, Data), addr, 8, aq, aq & rl, true)), + _ => internal_error(__FILE__, __LINE__, "Unexpected AMOCAS width") + }; + match (mval) { + MemException(e) => { handle_mem_exception(vaddr, e); RETIRE_FAIL }, + MemValue(loaded) => { + let success : bool = (loaded == rs2_val); + let result : xlenbits = if success then rd_val else loaded; + let rval : xlenbits = match width { + BYTE => sign_extend(loaded[7..0]), + HALF => sign_extend(loaded[15..0]), + WORD => sign_extend(loaded[31..0]), + DOUBLE => loaded + }; + let wval : MemoryOpResult(bool) = if success then { + match (width, sizeof(xlen)) { + (BYTE, _) => mem_write_value(addr, 1, result[7..0], aq & rl, rl, true), + (HALF, _) => mem_write_value(addr, 2, result[15..0], aq & rl, rl, true), + (WORD, _) => mem_write_value(addr, 4, result[31..0], aq & rl, rl, true), + (DOUBLE, 64) => mem_write_value(addr, 8, result, aq & rl, rl, true), + _ => internal_error(__FILE__, __LINE__, "Unexpected AMOCAS width") + } + } else { + MemValue(true) /* No write on compare failure */ + }; + match (wval) { + MemValue(true) => { X(rd) = rval; RETIRE_SUCCESS }, + MemValue(false) => { internal_error(__FILE__, __LINE__, "AMOCAS got false from mem_write_value") }, + MemException(e) => { handle_mem_exception(vaddr, e); RETIRE_FAIL } + } + } + } + } + } + } + } + } + } + } else { + handle_illegal(); + RETIRE_FAIL + } + } + +# SPDX-SnippetEnd diff --git a/spec/std/isa/inst/Zacas/amocas.q.yaml b/spec/std/isa/inst/Zacas/amocas.q.yaml index d711bb9de8..dff540f75f 100644 --- a/spec/std/isa/inst/Zacas/amocas.q.yaml +++ b/spec/std/isa/inst/Zacas/amocas.q.yaml @@ -1,70 +1,130 @@ # Copyright (c) Qualcomm Technologies, Inc. and/or its subsidiaries. + +# WARNING: This file is auto-generated from spec/std/isa/inst/Zacas/amocas.SIZE.AQRL.layout# Copyright (c) Abhijit Das(Sukuna0007Abhi) # SPDX-License-Identifier: BSD-3-Clause-Clear ---- # yaml-language-server: $schema=../../../../schemas/inst_schema.json $schema: "inst_schema.json#" kind: instruction name: amocas.q -long_name: Atomic Compare-and-Swap Quadword +long_name: Atomic compare-and-swap quadword description: | - For RV64, AMOCAS.Q atomically loads 128-bits of a data value from address - in xs1, compares the loaded value to a 128-bit value held in a register - pair consisting of xd and xd+1, and if the comparison is bitwise equal, - then stores the 128-bit value held in the register pair xs2 and xs2+1 to - the original address in xs1. The value loaded from memory is placed into - the register pair xd and xd+1. The instruction requires the first register - in the pair to be even numbered; encodings with odd-numbered registers - specified in xs2 and xd are reserved. When the first register of a source - register pair is x0, then both halves of the pair read as zero. When the - first register of a destination register pair is x0, then the entire - register result is discarded and neither destination register is written. - - Just as for AMOs in the A extension, AMOCAS.Q requires that the address held - in xs1 be naturally aligned to the size of the operand (i.e., sixteen-byte - aligned for quadwords). And the same exception options apply if the - address is not naturally aligned. - - Just as for AMOs in the A extension, the AMOCAS.Q optionally provides release - consistency semantics, using the aq and rl bits, to help implement - multiprocessor synchronization. The memory operation performed by an - AMOCAS.Q, when successful, has acquire semantics if aq bit is 1 and has - release semantics if rl bit is 1. The memory operation performed by an - AMOCAS.W/D/Q, when not successful, has acquire semantics if aq bit is 1 but - does not have release semantics, regardless of rl. - - A FENCE instruction may be used to order the memory read access and, if - produced, the memory write access by an AMOCAS.Q instruction. - - [Note] An unsuccessful AMOCAS.Q may either not perform a memory write or - may write back the old value loaded from memory. The memory write, if - produced, does not have release semantics, regardless of rl. - - An AMOCAS.Q instruction always requires write permissions. + Atomically: + * Load the quadword at address _xs1_ + * Write the loaded value into _xd_ + * Compare the loaded value with the value of register _xs2_ + * If equal, write the value of register _xs2+1_ to the address in _xs1_ definedBy: Zacas base: 64 assembly: xd, xs2, (xs1) encoding: - match: 00101------------100-----0101111 + match: 0010100----------100-----0101111 variables: - - name: aq - location: 26-26 - - name: rl - location: 25-25 - name: xs2 location: 24-20 - not: [1, 3, 5, 7, 9, 11, 13, 15, 17, 19, 21, 23, 25, 27, 29, 31] - name: xs1 location: 19-15 - name: xd location: 11-7 - not: [1, 3, 5, 7, 9, 11, 13, 15, 17, 19, 21, 23, 25, 27, 29, 31] access: s: always u: always vs: always vu: always -data_independent_timing: false operation(): | + if (!implemented?(ExtensionName::Zacas)) { + raise (ExceptionCode::IllegalInstruction, mode(), $encoding); + } + + XReg virtual_address = X[xs1]; + # TODO + # X[xd] = amocas128(virtual_address, X[xs2], X[xd], 1'b0, 1'b0, $encoding); + +# SPDX-SnippetBegin +# SPDX-FileCopyrightText: 2017-2025 Contributors to the RISCV Sail Model +# SPDX-License-Identifier: BSD-2-Clause +sail(): | + { + if extension("Zacas") then { + /* Get the address, X(rs1) (no offset). + * Some extensions perform additional checks on address validity. + */ + match ext_data_get_addr(rs1, zeros(), ReadWrite(Data, Data), width) { + Ext_DataAddr_Error(e) => { ext_handle_data_check_error(e); RETIRE_FAIL }, + Ext_DataAddr_OK(vaddr) => { + match translateAddr(vaddr, ReadWrite(Data, Data)) { + TR_Failure(e, _) => { handle_mem_exception(vaddr, e); RETIRE_FAIL }, + TR_Address(addr, _) => { + let eares : MemoryOpResult(unit) = match (width, sizeof(xlen)) { + (BYTE, _) => mem_write_ea(addr, 1, aq & rl, rl, true), + (HALF, _) => mem_write_ea(addr, 2, aq & rl, rl, true), + (WORD, _) => mem_write_ea(addr, 4, aq & rl, rl, true), + (DOUBLE, 64) => mem_write_ea(addr, 8, aq & rl, rl, true), + _ => internal_error(__FILE__, __LINE__, "Unexpected AMOCAS width") + }; + let rs2_val : xlenbits = match width { + BYTE => sign_extend(X(rs2)[7..0]), + HALF => sign_extend(X(rs2)[15..0]), + WORD => sign_extend(X(rs2)[31..0]), + DOUBLE => X(rs2) + }; + let rd_val : xlenbits = match width { + BYTE => sign_extend(X(rd)[7..0]), + HALF => sign_extend(X(rd)[15..0]), + WORD => sign_extend(X(rd)[31..0]), + DOUBLE => X(rd) + }; + match (eares) { + MemException(e) => { handle_mem_exception(vaddr, e); RETIRE_FAIL }, + MemValue(_) => { + let mval : MemoryOpResult(xlenbits) = match (width, sizeof(xlen)) { + (BYTE, _) => extend_value(false, mem_read(ReadWrite(Data, Data), addr, 1, aq, aq & rl, true)), + (HALF, _) => extend_value(false, mem_read(ReadWrite(Data, Data), addr, 2, aq, aq & rl, true)), + (WORD, _) => extend_value(false, mem_read(ReadWrite(Data, Data), addr, 4, aq, aq & rl, true)), + (DOUBLE, 64) => extend_value(false, mem_read(ReadWrite(Data, Data), addr, 8, aq, aq & rl, true)), + _ => internal_error(__FILE__, __LINE__, "Unexpected AMOCAS width") + }; + match (mval) { + MemException(e) => { handle_mem_exception(vaddr, e); RETIRE_FAIL }, + MemValue(loaded) => { + let success : bool = (loaded == rs2_val); + let result : xlenbits = if success then rd_val else loaded; + let rval : xlenbits = match width { + BYTE => sign_extend(loaded[7..0]), + HALF => sign_extend(loaded[15..0]), + WORD => sign_extend(loaded[31..0]), + DOUBLE => loaded + }; + let wval : MemoryOpResult(bool) = if success then { + match (width, sizeof(xlen)) { + (BYTE, _) => mem_write_value(addr, 1, result[7..0], aq & rl, rl, true), + (HALF, _) => mem_write_value(addr, 2, result[15..0], aq & rl, rl, true), + (WORD, _) => mem_write_value(addr, 4, result[31..0], aq & rl, rl, true), + (DOUBLE, 64) => mem_write_value(addr, 8, result, aq & rl, rl, true), + _ => internal_error(__FILE__, __LINE__, "Unexpected AMOCAS width") + } + } else { + MemValue(true) /* No write on compare failure */ + }; + match (wval) { + MemValue(true) => { X(rd) = rval; RETIRE_SUCCESS }, + MemValue(false) => { internal_error(__FILE__, __LINE__, "AMOCAS got false from mem_write_value") }, + MemException(e) => { handle_mem_exception(vaddr, e); RETIRE_FAIL } + } + } + } + } + } + } + } + } + } + } else { + handle_illegal(); + RETIRE_FAIL + } + } + +# SPDX-SnippetEnd diff --git a/spec/std/isa/inst/Zacas/amocas.w.aq.yaml b/spec/std/isa/inst/Zacas/amocas.w.aq.yaml new file mode 100644 index 0000000000..bf522deb7b --- /dev/null +++ b/spec/std/isa/inst/Zacas/amocas.w.aq.yaml @@ -0,0 +1,131 @@ +# Copyright (c) Qualcomm Technologies, Inc. and/or its subsidiaries. + +# WARNING: This file is auto-generated from spec/std/isa/inst/Zacas/amocas.SIZE.AQRL.layout# Copyright (c) Abhijit Das(Sukuna0007Abhi) +# SPDX-License-Identifier: BSD-3-Clause-Clear + +# yaml-language-server: $schema=../../../../schemas/inst_schema.json + +$schema: "inst_schema.json#" +kind: instruction +name: amocas.w.aq +long_name: Atomic compare-and-swap word (acquire) +description: | + Atomically with acquire ordering: + + * Load the word at address _xs1_ + * Write the sign-extended value into _xd_ + * Compare the loaded value with the least-significant word of register _xs2_ + * If equal, write the least-significant word of register _xs2+1_ to the address in _xs1_ +definedBy: Zacas +assembly: xd, xs2, (xs1) +encoding: + match: 0010110----------010-----0101111 + variables: + - name: xs2 + location: 24-20 + - name: xs1 + location: 19-15 + - name: xd + location: 11-7 +access: + s: always + u: always + vs: always + vu: always +operation(): | + if (!implemented?(ExtensionName::Zacas)) { + raise (ExceptionCode::IllegalInstruction, mode(), $encoding); + } + + memory_model_acquire(); + + XReg virtual_address = X[xs1]; + # TODO + # X[xd] = amocas32(virtual_address, X[xs2][31:0], X[xd][31:0], 1'b1, 1'b0, $encoding); + +# SPDX-SnippetBegin +# SPDX-FileCopyrightText: 2017-2025 Contributors to the RISCV Sail Model +# SPDX-License-Identifier: BSD-2-Clause +sail(): | + { + if extension("Zacas") then { + /* Get the address, X(rs1) (no offset). + * Some extensions perform additional checks on address validity. + */ + match ext_data_get_addr(rs1, zeros(), ReadWrite(Data, Data), width) { + Ext_DataAddr_Error(e) => { ext_handle_data_check_error(e); RETIRE_FAIL }, + Ext_DataAddr_OK(vaddr) => { + match translateAddr(vaddr, ReadWrite(Data, Data)) { + TR_Failure(e, _) => { handle_mem_exception(vaddr, e); RETIRE_FAIL }, + TR_Address(addr, _) => { + let eares : MemoryOpResult(unit) = match (width, sizeof(xlen)) { + (BYTE, _) => mem_write_ea(addr, 1, aq & rl, rl, true), + (HALF, _) => mem_write_ea(addr, 2, aq & rl, rl, true), + (WORD, _) => mem_write_ea(addr, 4, aq & rl, rl, true), + (DOUBLE, 64) => mem_write_ea(addr, 8, aq & rl, rl, true), + _ => internal_error(__FILE__, __LINE__, "Unexpected AMOCAS width") + }; + let rs2_val : xlenbits = match width { + BYTE => sign_extend(X(rs2)[7..0]), + HALF => sign_extend(X(rs2)[15..0]), + WORD => sign_extend(X(rs2)[31..0]), + DOUBLE => X(rs2) + }; + let rd_val : xlenbits = match width { + BYTE => sign_extend(X(rd)[7..0]), + HALF => sign_extend(X(rd)[15..0]), + WORD => sign_extend(X(rd)[31..0]), + DOUBLE => X(rd) + }; + match (eares) { + MemException(e) => { handle_mem_exception(vaddr, e); RETIRE_FAIL }, + MemValue(_) => { + let mval : MemoryOpResult(xlenbits) = match (width, sizeof(xlen)) { + (BYTE, _) => extend_value(false, mem_read(ReadWrite(Data, Data), addr, 1, aq, aq & rl, true)), + (HALF, _) => extend_value(false, mem_read(ReadWrite(Data, Data), addr, 2, aq, aq & rl, true)), + (WORD, _) => extend_value(false, mem_read(ReadWrite(Data, Data), addr, 4, aq, aq & rl, true)), + (DOUBLE, 64) => extend_value(false, mem_read(ReadWrite(Data, Data), addr, 8, aq, aq & rl, true)), + _ => internal_error(__FILE__, __LINE__, "Unexpected AMOCAS width") + }; + match (mval) { + MemException(e) => { handle_mem_exception(vaddr, e); RETIRE_FAIL }, + MemValue(loaded) => { + let success : bool = (loaded == rs2_val); + let result : xlenbits = if success then rd_val else loaded; + let rval : xlenbits = match width { + BYTE => sign_extend(loaded[7..0]), + HALF => sign_extend(loaded[15..0]), + WORD => sign_extend(loaded[31..0]), + DOUBLE => loaded + }; + let wval : MemoryOpResult(bool) = if success then { + match (width, sizeof(xlen)) { + (BYTE, _) => mem_write_value(addr, 1, result[7..0], aq & rl, rl, true), + (HALF, _) => mem_write_value(addr, 2, result[15..0], aq & rl, rl, true), + (WORD, _) => mem_write_value(addr, 4, result[31..0], aq & rl, rl, true), + (DOUBLE, 64) => mem_write_value(addr, 8, result, aq & rl, rl, true), + _ => internal_error(__FILE__, __LINE__, "Unexpected AMOCAS width") + } + } else { + MemValue(true) /* No write on compare failure */ + }; + match (wval) { + MemValue(true) => { X(rd) = rval; RETIRE_SUCCESS }, + MemValue(false) => { internal_error(__FILE__, __LINE__, "AMOCAS got false from mem_write_value") }, + MemException(e) => { handle_mem_exception(vaddr, e); RETIRE_FAIL } + } + } + } + } + } + } + } + } + } + } else { + handle_illegal(); + RETIRE_FAIL + } + } + +# SPDX-SnippetEnd diff --git a/spec/std/isa/inst/Zacas/amocas.w.aqrl.yaml b/spec/std/isa/inst/Zacas/amocas.w.aqrl.yaml new file mode 100644 index 0000000000..98f134766e --- /dev/null +++ b/spec/std/isa/inst/Zacas/amocas.w.aqrl.yaml @@ -0,0 +1,133 @@ +# Copyright (c) Qualcomm Technologies, Inc. and/or its subsidiaries. + +# WARNING: This file is auto-generated from spec/std/isa/inst/Zacas/amocas.SIZE.AQRL.layout# Copyright (c) Abhijit Das(Sukuna0007Abhi) +# SPDX-License-Identifier: BSD-3-Clause-Clear + +# yaml-language-server: $schema=../../../../schemas/inst_schema.json + +$schema: "inst_schema.json#" +kind: instruction +name: amocas.w.aqrl +long_name: Atomic compare-and-swap word (acquire-release) +description: | + Atomically with acquire and release ordering: + + * Load the word at address _xs1_ + * Write the sign-extended value into _xd_ + * Compare the loaded value with the least-significant word of register _xs2_ + * If equal, write the least-significant word of register _xs2+1_ to the address in _xs1_ +definedBy: Zacas +assembly: xd, xs2, (xs1) +encoding: + match: 0010111----------010-----0101111 + variables: + - name: xs2 + location: 24-20 + - name: xs1 + location: 19-15 + - name: xd + location: 11-7 +access: + s: always + u: always + vs: always + vu: always +operation(): | + if (!implemented?(ExtensionName::Zacas)) { + raise (ExceptionCode::IllegalInstruction, mode(), $encoding); + } + + memory_model_acquire(); + + XReg virtual_address = X[xs1]; + # TODO + # X[xd] = amocas32(virtual_address, X[xs2][31:0], X[xd][31:0], 1'b1, 1'b1, $encoding); + + memory_model_release(); + +# SPDX-SnippetBegin +# SPDX-FileCopyrightText: 2017-2025 Contributors to the RISCV Sail Model +# SPDX-License-Identifier: BSD-2-Clause +sail(): | + { + if extension("Zacas") then { + /* Get the address, X(rs1) (no offset). + * Some extensions perform additional checks on address validity. + */ + match ext_data_get_addr(rs1, zeros(), ReadWrite(Data, Data), width) { + Ext_DataAddr_Error(e) => { ext_handle_data_check_error(e); RETIRE_FAIL }, + Ext_DataAddr_OK(vaddr) => { + match translateAddr(vaddr, ReadWrite(Data, Data)) { + TR_Failure(e, _) => { handle_mem_exception(vaddr, e); RETIRE_FAIL }, + TR_Address(addr, _) => { + let eares : MemoryOpResult(unit) = match (width, sizeof(xlen)) { + (BYTE, _) => mem_write_ea(addr, 1, aq & rl, rl, true), + (HALF, _) => mem_write_ea(addr, 2, aq & rl, rl, true), + (WORD, _) => mem_write_ea(addr, 4, aq & rl, rl, true), + (DOUBLE, 64) => mem_write_ea(addr, 8, aq & rl, rl, true), + _ => internal_error(__FILE__, __LINE__, "Unexpected AMOCAS width") + }; + let rs2_val : xlenbits = match width { + BYTE => sign_extend(X(rs2)[7..0]), + HALF => sign_extend(X(rs2)[15..0]), + WORD => sign_extend(X(rs2)[31..0]), + DOUBLE => X(rs2) + }; + let rd_val : xlenbits = match width { + BYTE => sign_extend(X(rd)[7..0]), + HALF => sign_extend(X(rd)[15..0]), + WORD => sign_extend(X(rd)[31..0]), + DOUBLE => X(rd) + }; + match (eares) { + MemException(e) => { handle_mem_exception(vaddr, e); RETIRE_FAIL }, + MemValue(_) => { + let mval : MemoryOpResult(xlenbits) = match (width, sizeof(xlen)) { + (BYTE, _) => extend_value(false, mem_read(ReadWrite(Data, Data), addr, 1, aq, aq & rl, true)), + (HALF, _) => extend_value(false, mem_read(ReadWrite(Data, Data), addr, 2, aq, aq & rl, true)), + (WORD, _) => extend_value(false, mem_read(ReadWrite(Data, Data), addr, 4, aq, aq & rl, true)), + (DOUBLE, 64) => extend_value(false, mem_read(ReadWrite(Data, Data), addr, 8, aq, aq & rl, true)), + _ => internal_error(__FILE__, __LINE__, "Unexpected AMOCAS width") + }; + match (mval) { + MemException(e) => { handle_mem_exception(vaddr, e); RETIRE_FAIL }, + MemValue(loaded) => { + let success : bool = (loaded == rs2_val); + let result : xlenbits = if success then rd_val else loaded; + let rval : xlenbits = match width { + BYTE => sign_extend(loaded[7..0]), + HALF => sign_extend(loaded[15..0]), + WORD => sign_extend(loaded[31..0]), + DOUBLE => loaded + }; + let wval : MemoryOpResult(bool) = if success then { + match (width, sizeof(xlen)) { + (BYTE, _) => mem_write_value(addr, 1, result[7..0], aq & rl, rl, true), + (HALF, _) => mem_write_value(addr, 2, result[15..0], aq & rl, rl, true), + (WORD, _) => mem_write_value(addr, 4, result[31..0], aq & rl, rl, true), + (DOUBLE, 64) => mem_write_value(addr, 8, result, aq & rl, rl, true), + _ => internal_error(__FILE__, __LINE__, "Unexpected AMOCAS width") + } + } else { + MemValue(true) /* No write on compare failure */ + }; + match (wval) { + MemValue(true) => { X(rd) = rval; RETIRE_SUCCESS }, + MemValue(false) => { internal_error(__FILE__, __LINE__, "AMOCAS got false from mem_write_value") }, + MemException(e) => { handle_mem_exception(vaddr, e); RETIRE_FAIL } + } + } + } + } + } + } + } + } + } + } else { + handle_illegal(); + RETIRE_FAIL + } + } + +# SPDX-SnippetEnd diff --git a/spec/std/isa/inst/Zacas/amocas.w.rl.yaml b/spec/std/isa/inst/Zacas/amocas.w.rl.yaml new file mode 100644 index 0000000000..85ae74c3cb --- /dev/null +++ b/spec/std/isa/inst/Zacas/amocas.w.rl.yaml @@ -0,0 +1,131 @@ +# Copyright (c) Qualcomm Technologies, Inc. and/or its subsidiaries. + +# WARNING: This file is auto-generated from spec/std/isa/inst/Zacas/amocas.SIZE.AQRL.layout# Copyright (c) Abhijit Das(Sukuna0007Abhi) +# SPDX-License-Identifier: BSD-3-Clause-Clear + +# yaml-language-server: $schema=../../../../schemas/inst_schema.json + +$schema: "inst_schema.json#" +kind: instruction +name: amocas.w.rl +long_name: Atomic compare-and-swap word (release) +description: | + Atomically with release ordering: + + * Load the word at address _xs1_ + * Write the sign-extended value into _xd_ + * Compare the loaded value with the least-significant word of register _xs2_ + * If equal, write the least-significant word of register _xs2+1_ to the address in _xs1_ +definedBy: Zacas +assembly: xd, xs2, (xs1) +encoding: + match: 0010101----------010-----0101111 + variables: + - name: xs2 + location: 24-20 + - name: xs1 + location: 19-15 + - name: xd + location: 11-7 +access: + s: always + u: always + vs: always + vu: always +operation(): | + if (!implemented?(ExtensionName::Zacas)) { + raise (ExceptionCode::IllegalInstruction, mode(), $encoding); + } + + XReg virtual_address = X[xs1]; + # TODO + # X[xd] = amocas32(virtual_address, X[xs2][31:0], X[xd][31:0], 1'b0, 1'b1, $encoding); + + memory_model_release(); + +# SPDX-SnippetBegin +# SPDX-FileCopyrightText: 2017-2025 Contributors to the RISCV Sail Model +# SPDX-License-Identifier: BSD-2-Clause +sail(): | + { + if extension("Zacas") then { + /* Get the address, X(rs1) (no offset). + * Some extensions perform additional checks on address validity. + */ + match ext_data_get_addr(rs1, zeros(), ReadWrite(Data, Data), width) { + Ext_DataAddr_Error(e) => { ext_handle_data_check_error(e); RETIRE_FAIL }, + Ext_DataAddr_OK(vaddr) => { + match translateAddr(vaddr, ReadWrite(Data, Data)) { + TR_Failure(e, _) => { handle_mem_exception(vaddr, e); RETIRE_FAIL }, + TR_Address(addr, _) => { + let eares : MemoryOpResult(unit) = match (width, sizeof(xlen)) { + (BYTE, _) => mem_write_ea(addr, 1, aq & rl, rl, true), + (HALF, _) => mem_write_ea(addr, 2, aq & rl, rl, true), + (WORD, _) => mem_write_ea(addr, 4, aq & rl, rl, true), + (DOUBLE, 64) => mem_write_ea(addr, 8, aq & rl, rl, true), + _ => internal_error(__FILE__, __LINE__, "Unexpected AMOCAS width") + }; + let rs2_val : xlenbits = match width { + BYTE => sign_extend(X(rs2)[7..0]), + HALF => sign_extend(X(rs2)[15..0]), + WORD => sign_extend(X(rs2)[31..0]), + DOUBLE => X(rs2) + }; + let rd_val : xlenbits = match width { + BYTE => sign_extend(X(rd)[7..0]), + HALF => sign_extend(X(rd)[15..0]), + WORD => sign_extend(X(rd)[31..0]), + DOUBLE => X(rd) + }; + match (eares) { + MemException(e) => { handle_mem_exception(vaddr, e); RETIRE_FAIL }, + MemValue(_) => { + let mval : MemoryOpResult(xlenbits) = match (width, sizeof(xlen)) { + (BYTE, _) => extend_value(false, mem_read(ReadWrite(Data, Data), addr, 1, aq, aq & rl, true)), + (HALF, _) => extend_value(false, mem_read(ReadWrite(Data, Data), addr, 2, aq, aq & rl, true)), + (WORD, _) => extend_value(false, mem_read(ReadWrite(Data, Data), addr, 4, aq, aq & rl, true)), + (DOUBLE, 64) => extend_value(false, mem_read(ReadWrite(Data, Data), addr, 8, aq, aq & rl, true)), + _ => internal_error(__FILE__, __LINE__, "Unexpected AMOCAS width") + }; + match (mval) { + MemException(e) => { handle_mem_exception(vaddr, e); RETIRE_FAIL }, + MemValue(loaded) => { + let success : bool = (loaded == rs2_val); + let result : xlenbits = if success then rd_val else loaded; + let rval : xlenbits = match width { + BYTE => sign_extend(loaded[7..0]), + HALF => sign_extend(loaded[15..0]), + WORD => sign_extend(loaded[31..0]), + DOUBLE => loaded + }; + let wval : MemoryOpResult(bool) = if success then { + match (width, sizeof(xlen)) { + (BYTE, _) => mem_write_value(addr, 1, result[7..0], aq & rl, rl, true), + (HALF, _) => mem_write_value(addr, 2, result[15..0], aq & rl, rl, true), + (WORD, _) => mem_write_value(addr, 4, result[31..0], aq & rl, rl, true), + (DOUBLE, 64) => mem_write_value(addr, 8, result, aq & rl, rl, true), + _ => internal_error(__FILE__, __LINE__, "Unexpected AMOCAS width") + } + } else { + MemValue(true) /* No write on compare failure */ + }; + match (wval) { + MemValue(true) => { X(rd) = rval; RETIRE_SUCCESS }, + MemValue(false) => { internal_error(__FILE__, __LINE__, "AMOCAS got false from mem_write_value") }, + MemException(e) => { handle_mem_exception(vaddr, e); RETIRE_FAIL } + } + } + } + } + } + } + } + } + } + } else { + handle_illegal(); + RETIRE_FAIL + } + } + +# SPDX-SnippetEnd diff --git a/spec/std/isa/inst/Zacas/amocas.w.yaml b/spec/std/isa/inst/Zacas/amocas.w.yaml index 4fca32ea10..c317df6620 100644 --- a/spec/std/isa/inst/Zacas/amocas.w.yaml +++ b/spec/std/isa/inst/Zacas/amocas.w.yaml @@ -1,57 +1,26 @@ # Copyright (c) Qualcomm Technologies, Inc. and/or its subsidiaries. + +# WARNING: This file is auto-generated from spec/std/isa/inst/Zacas/amocas.SIZE.AQRL.layout# Copyright (c) Abhijit Das(Sukuna0007Abhi) # SPDX-License-Identifier: BSD-3-Clause-Clear ---- # yaml-language-server: $schema=../../../../schemas/inst_schema.json $schema: "inst_schema.json#" kind: instruction name: amocas.w -long_name: Atomic Compare-and-Swap Word +long_name: Atomic compare-and-swap word description: | - For RV32, AMOCAS.W atomically loads a 32-bit data value from address in xs1, - compares the loaded value to the 32-bit value held in xd, and if the - comparison is bitwise equal, then stores the 32-bit value held in xs2 to the - original address in xs1. The value loaded from memory is placed into - register xd. - - For RV64, AMOCAS.W atomically loads a 32-bit data value from address in xs1, - compares the loaded value to the lower 32 bits of the value held in xd, and - if the comparison is bitwise equal, then stores the lower 32 bits of the - value held in xs2 to the original address in xs1. The 32-bit value loaded - from memory is sign-extended and is placed into register xd. - - Just as for AMOs in the A extension, AMOCAS.W requires that the address held - in xs1 be naturally aligned to the size of the operand (i.e., four-byte - aligned for words). And the same exception options apply if the address is - not naturally aligned. - - Just as for AMOs in the A extension, the AMOCAS.W optionally provides release - consistency semantics, using the aq and rl bits, to help implement - multiprocessor synchronization. The memory operation performed by an - AMOCAS.W, when successful, has acquire semantics if aq bit is 1 and has - release semantics if rl bit is 1. The memory operation performed by an - AMOCAS.W/D/Q, when not successful, has acquire semantics if aq bit is 1 but - does not have release semantics, regardless of rl. - - A FENCE instruction may be used to order the memory read access and, if - produced, the memory write access by an AMOCAS.W instruction. - - [Note] An unsuccessful AMOCAS.W may either not perform a memory write or may - write back the old value loaded from memory. The memory write, if produced, - does not have release semantics, regardless of rl. - - An AMOCAS.W instruction always requires write permissions. + Atomically: + * Load the word at address _xs1_ + * Write the sign-extended value into _xd_ + * Compare the loaded value with the least-significant word of register _xs2_ + * If equal, write the least-significant word of register _xs2+1_ to the address in _xs1_ definedBy: Zacas assembly: xd, xs2, (xs1) encoding: - match: 00101------------010-----0101111 + match: 0010100----------010-----0101111 variables: - - name: aq - location: 26-26 - - name: rl - location: 25-25 - name: xs2 location: 24-20 - name: xs1 @@ -63,5 +32,98 @@ access: u: always vs: always vu: always -data_independent_timing: false operation(): | + if (!implemented?(ExtensionName::Zacas)) { + raise (ExceptionCode::IllegalInstruction, mode(), $encoding); + } + + XReg virtual_address = X[xs1]; + # TODO + # X[xd] = amocas32(virtual_address, X[xs2][31:0], X[xd][31:0], 1'b0, 1'b0, $encoding); + +# SPDX-SnippetBegin +# SPDX-FileCopyrightText: 2017-2025 Contributors to the RISCV Sail Model +# SPDX-License-Identifier: BSD-2-Clause +sail(): | + { + if extension("Zacas") then { + /* Get the address, X(rs1) (no offset). + * Some extensions perform additional checks on address validity. + */ + match ext_data_get_addr(rs1, zeros(), ReadWrite(Data, Data), width) { + Ext_DataAddr_Error(e) => { ext_handle_data_check_error(e); RETIRE_FAIL }, + Ext_DataAddr_OK(vaddr) => { + match translateAddr(vaddr, ReadWrite(Data, Data)) { + TR_Failure(e, _) => { handle_mem_exception(vaddr, e); RETIRE_FAIL }, + TR_Address(addr, _) => { + let eares : MemoryOpResult(unit) = match (width, sizeof(xlen)) { + (BYTE, _) => mem_write_ea(addr, 1, aq & rl, rl, true), + (HALF, _) => mem_write_ea(addr, 2, aq & rl, rl, true), + (WORD, _) => mem_write_ea(addr, 4, aq & rl, rl, true), + (DOUBLE, 64) => mem_write_ea(addr, 8, aq & rl, rl, true), + _ => internal_error(__FILE__, __LINE__, "Unexpected AMOCAS width") + }; + let rs2_val : xlenbits = match width { + BYTE => sign_extend(X(rs2)[7..0]), + HALF => sign_extend(X(rs2)[15..0]), + WORD => sign_extend(X(rs2)[31..0]), + DOUBLE => X(rs2) + }; + let rd_val : xlenbits = match width { + BYTE => sign_extend(X(rd)[7..0]), + HALF => sign_extend(X(rd)[15..0]), + WORD => sign_extend(X(rd)[31..0]), + DOUBLE => X(rd) + }; + match (eares) { + MemException(e) => { handle_mem_exception(vaddr, e); RETIRE_FAIL }, + MemValue(_) => { + let mval : MemoryOpResult(xlenbits) = match (width, sizeof(xlen)) { + (BYTE, _) => extend_value(false, mem_read(ReadWrite(Data, Data), addr, 1, aq, aq & rl, true)), + (HALF, _) => extend_value(false, mem_read(ReadWrite(Data, Data), addr, 2, aq, aq & rl, true)), + (WORD, _) => extend_value(false, mem_read(ReadWrite(Data, Data), addr, 4, aq, aq & rl, true)), + (DOUBLE, 64) => extend_value(false, mem_read(ReadWrite(Data, Data), addr, 8, aq, aq & rl, true)), + _ => internal_error(__FILE__, __LINE__, "Unexpected AMOCAS width") + }; + match (mval) { + MemException(e) => { handle_mem_exception(vaddr, e); RETIRE_FAIL }, + MemValue(loaded) => { + let success : bool = (loaded == rs2_val); + let result : xlenbits = if success then rd_val else loaded; + let rval : xlenbits = match width { + BYTE => sign_extend(loaded[7..0]), + HALF => sign_extend(loaded[15..0]), + WORD => sign_extend(loaded[31..0]), + DOUBLE => loaded + }; + let wval : MemoryOpResult(bool) = if success then { + match (width, sizeof(xlen)) { + (BYTE, _) => mem_write_value(addr, 1, result[7..0], aq & rl, rl, true), + (HALF, _) => mem_write_value(addr, 2, result[15..0], aq & rl, rl, true), + (WORD, _) => mem_write_value(addr, 4, result[31..0], aq & rl, rl, true), + (DOUBLE, 64) => mem_write_value(addr, 8, result, aq & rl, rl, true), + _ => internal_error(__FILE__, __LINE__, "Unexpected AMOCAS width") + } + } else { + MemValue(true) /* No write on compare failure */ + }; + match (wval) { + MemValue(true) => { X(rd) = rval; RETIRE_SUCCESS }, + MemValue(false) => { internal_error(__FILE__, __LINE__, "AMOCAS got false from mem_write_value") }, + MemException(e) => { handle_mem_exception(vaddr, e); RETIRE_FAIL } + } + } + } + } + } + } + } + } + } + } else { + handle_illegal(); + RETIRE_FAIL + } + } + +# SPDX-SnippetEnd