about summary refs log tree commit diff
path: root/library/stdarch
diff options
context:
space:
mode:
authorTsukasa OI <floss_rust@irq.a4lg.com>2025-09-13 21:59:39 +0000
committerTsukasa OI <floss_rust@irq.a4lg.com>2025-09-14 05:08:19 +0000
commit8df078a3f0071b311be2449407ae523f89ca6a33 (patch)
treebf2cc8066b26eb3363c2a04e81c2bc28a9d33032 /library/stdarch
parent33387434c539d63a1a9a4f1e9793219256ac9293 (diff)
downloadrust-8df078a3f0071b311be2449407ae523f89ca6a33.tar.gz
rust-8df078a3f0071b311be2449407ae523f89ca6a33.zip
RISC-V: Improvements of inline assembly uses
This commit performs various improvements (better register allocation,
less register clobbering on the worst case and better readability) of
RISC-V inline assembly use cases.

Note that it does not change the `p` module (which defines the "P"
extension draft instructions but very likely to change).

1.  Use `lateout` as possible.
    Unlike `out(reg)` and `in(reg)` pair, `lateout(reg)` and `in(reg)`
    can share the same register because they state that the late-output
    register is written after all the reads are performed.
    It can improve register allocation.
2.  Add `preserves_flags` option as possible.
    While RISC-V doesn't have _regular_ condition codes, RISC-V inline
    assembly in the Rust language assumes that some registers
    (mainly vector state registers) may be overwritten by default.
    By adding `preserves_flags` to the intrinsics corresponding
    instructions without overwriting them, it can minimize register
    clobbering on the worst case.
3.  Use trailing semicolon.
    As `asm!` declares an action and it doesn't return a value by
    itself, it would be better to have trailing semicolon to denote that
    an `asm!` call is effectively a statement.
4.  Make most of `asm!` calls multi-lined.
    `rustfmt` makes some simple (yet long) `asm!` calls multi-lined but
    it does not perform formatting of complex `asm!` calls with inputs
    and/or outputs.  To keep consistency, it makes most of the `asm!`
    calls multi-lined.
Diffstat (limited to 'library/stdarch')
-rw-r--r--library/stdarch/crates/core_arch/src/riscv64/mod.rs21
-rw-r--r--library/stdarch/crates/core_arch/src/riscv_shared/mod.rs245
2 files changed, 215 insertions, 51 deletions
diff --git a/library/stdarch/crates/core_arch/src/riscv64/mod.rs b/library/stdarch/crates/core_arch/src/riscv64/mod.rs
index 0e860f6f2ad..a7efc0c7f58 100644
--- a/library/stdarch/crates/core_arch/src/riscv64/mod.rs
+++ b/library/stdarch/crates/core_arch/src/riscv64/mod.rs
@@ -20,7 +20,12 @@ pub use zk::*;
 #[unstable(feature = "riscv_ext_intrinsics", issue = "114544")]
 pub unsafe fn hlv_wu(src: *const u32) -> u32 {
     let value: u32;
-    asm!(".insn i 0x73, 0x4, {}, {}, 0x681", out(reg) value, in(reg) src, options(readonly, nostack));
+    asm!(
+        ".insn i 0x73, 0x4, {}, {}, 0x681",
+        lateout(reg) value,
+        in(reg) src,
+        options(readonly, nostack, preserves_flags)
+    );
     value
 }
 
@@ -38,7 +43,12 @@ pub unsafe fn hlv_wu(src: *const u32) -> u32 {
 #[unstable(feature = "riscv_ext_intrinsics", issue = "114544")]
 pub unsafe fn hlv_d(src: *const i64) -> i64 {
     let value: i64;
-    asm!(".insn i 0x73, 0x4, {}, {}, 0x6C0", out(reg) value, in(reg) src, options(readonly, nostack));
+    asm!(
+        ".insn i 0x73, 0x4, {}, {}, 0x6C0",
+        lateout(reg) value,
+        in(reg) src,
+        options(readonly, nostack, preserves_flags)
+    );
     value
 }
 
@@ -53,5 +63,10 @@ pub unsafe fn hlv_d(src: *const i64) -> i64 {
 #[inline]
 #[unstable(feature = "riscv_ext_intrinsics", issue = "114544")]
 pub unsafe fn hsv_d(dst: *mut i64, src: i64) {
-    asm!(".insn r 0x73, 0x4, 0x37, x0, {}, {}", in(reg) dst, in(reg) src, options(nostack));
+    asm!(
+        ".insn r 0x73, 0x4, 0x37, x0, {}, {}",
+        in(reg) dst,
+        in(reg) src,
+        options(nostack, preserves_flags)
+    );
 }
diff --git a/library/stdarch/crates/core_arch/src/riscv_shared/mod.rs b/library/stdarch/crates/core_arch/src/riscv_shared/mod.rs
index 3ce24324de2..1bd147a6480 100644
--- a/library/stdarch/crates/core_arch/src/riscv_shared/mod.rs
+++ b/library/stdarch/crates/core_arch/src/riscv_shared/mod.rs
@@ -44,7 +44,12 @@ use crate::arch::asm;
 #[inline]
 #[unstable(feature = "riscv_ext_intrinsics", issue = "114544")]
 pub fn pause() {
-    unsafe { asm!(".insn i 0x0F, 0, x0, x0, 0x010", options(nomem, nostack)) }
+    unsafe {
+        asm!(
+            ".insn i 0x0F, 0, x0, x0, 0x010",
+            options(nomem, nostack, preserves_flags)
+        );
+    }
 }
 
 /// Generates the `NOP` instruction
@@ -54,7 +59,9 @@ pub fn pause() {
 #[inline]
 #[unstable(feature = "riscv_ext_intrinsics", issue = "114544")]
 pub fn nop() {
-    unsafe { asm!("nop", options(nomem, nostack)) }
+    unsafe {
+        asm!("nop", options(nomem, nostack, preserves_flags));
+    }
 }
 
 /// Generates the `WFI` instruction
@@ -65,7 +72,7 @@ pub fn nop() {
 #[inline]
 #[unstable(feature = "riscv_ext_intrinsics", issue = "114544")]
 pub unsafe fn wfi() {
-    asm!("wfi", options(nomem, nostack))
+    asm!("wfi", options(nomem, nostack, preserves_flags));
 }
 
 /// Generates the `FENCE.I` instruction
@@ -78,7 +85,7 @@ pub unsafe fn wfi() {
 #[inline]
 #[unstable(feature = "riscv_ext_intrinsics", issue = "114544")]
 pub unsafe fn fence_i() {
-    asm!("fence.i", options(nostack))
+    asm!("fence.i", options(nostack, preserves_flags));
 }
 
 /// Supervisor memory management fence for given virtual address and address space
@@ -92,7 +99,7 @@ pub unsafe fn fence_i() {
 #[inline]
 #[unstable(feature = "riscv_ext_intrinsics", issue = "114544")]
 pub unsafe fn sfence_vma(vaddr: usize, asid: usize) {
-    asm!("sfence.vma {}, {}", in(reg) vaddr, in(reg) asid, options(nostack))
+    asm!("sfence.vma {}, {}", in(reg) vaddr, in(reg) asid, options(nostack, preserves_flags));
 }
 
 /// Supervisor memory management fence for given virtual address
@@ -104,7 +111,7 @@ pub unsafe fn sfence_vma(vaddr: usize, asid: usize) {
 #[inline]
 #[unstable(feature = "riscv_ext_intrinsics", issue = "114544")]
 pub unsafe fn sfence_vma_vaddr(vaddr: usize) {
-    asm!("sfence.vma {}, x0", in(reg) vaddr, options(nostack))
+    asm!("sfence.vma {}, x0", in(reg) vaddr, options(nostack, preserves_flags));
 }
 
 /// Supervisor memory management fence for given address space
@@ -118,7 +125,7 @@ pub unsafe fn sfence_vma_vaddr(vaddr: usize) {
 #[inline]
 #[unstable(feature = "riscv_ext_intrinsics", issue = "114544")]
 pub unsafe fn sfence_vma_asid(asid: usize) {
-    asm!("sfence.vma x0, {}", in(reg) asid, options(nostack))
+    asm!("sfence.vma x0, {}", in(reg) asid, options(nostack, preserves_flags));
 }
 
 /// Supervisor memory management fence for all address spaces and virtual addresses
@@ -129,7 +136,7 @@ pub unsafe fn sfence_vma_asid(asid: usize) {
 #[inline]
 #[unstable(feature = "riscv_ext_intrinsics", issue = "114544")]
 pub unsafe fn sfence_vma_all() {
-    asm!("sfence.vma", options(nostack))
+    asm!("sfence.vma", options(nostack, preserves_flags));
 }
 
 /// Invalidate supervisor translation cache for given virtual address and address space
@@ -139,8 +146,13 @@ pub unsafe fn sfence_vma_all() {
 #[inline]
 #[unstable(feature = "riscv_ext_intrinsics", issue = "114544")]
 pub unsafe fn sinval_vma(vaddr: usize, asid: usize) {
-    // asm!("sinval.vma {}, {}", in(reg) vaddr, in(reg) asid, options(nostack))
-    asm!(".insn r 0x73, 0, 0x0B, x0, {}, {}", in(reg) vaddr, in(reg) asid, options(nostack))
+    // asm!("sinval.vma {}, {}", in(reg) vaddr, in(reg) asid, options(nostack, preserves_flags));
+    asm!(
+        ".insn r 0x73, 0, 0x0B, x0, {}, {}",
+        in(reg) vaddr,
+        in(reg) asid,
+        options(nostack, preserves_flags)
+    );
 }
 
 /// Invalidate supervisor translation cache for given virtual address
@@ -150,7 +162,11 @@ pub unsafe fn sinval_vma(vaddr: usize, asid: usize) {
 #[inline]
 #[unstable(feature = "riscv_ext_intrinsics", issue = "114544")]
 pub unsafe fn sinval_vma_vaddr(vaddr: usize) {
-    asm!(".insn r 0x73, 0, 0x0B, x0, {}, x0", in(reg) vaddr, options(nostack))
+    asm!(
+        ".insn r 0x73, 0, 0x0B, x0, {}, x0",
+        in(reg) vaddr,
+        options(nostack, preserves_flags)
+    );
 }
 
 /// Invalidate supervisor translation cache for given address space
@@ -160,7 +176,11 @@ pub unsafe fn sinval_vma_vaddr(vaddr: usize) {
 #[inline]
 #[unstable(feature = "riscv_ext_intrinsics", issue = "114544")]
 pub unsafe fn sinval_vma_asid(asid: usize) {
-    asm!(".insn r 0x73, 0, 0x0B, x0, x0, {}", in(reg) asid, options(nostack))
+    asm!(
+        ".insn r 0x73, 0, 0x0B, x0, x0, {}",
+        in(reg) asid,
+        options(nostack, preserves_flags)
+    );
 }
 
 /// Invalidate supervisor translation cache for all address spaces and virtual addresses
@@ -170,7 +190,10 @@ pub unsafe fn sinval_vma_asid(asid: usize) {
 #[inline]
 #[unstable(feature = "riscv_ext_intrinsics", issue = "114544")]
 pub unsafe fn sinval_vma_all() {
-    asm!(".insn r 0x73, 0, 0x0B, x0, x0, x0", options(nostack))
+    asm!(
+        ".insn r 0x73, 0, 0x0B, x0, x0, x0",
+        options(nostack, preserves_flags)
+    );
 }
 
 /// Generates the `SFENCE.W.INVAL` instruction
@@ -180,8 +203,11 @@ pub unsafe fn sinval_vma_all() {
 #[inline]
 #[unstable(feature = "riscv_ext_intrinsics", issue = "114544")]
 pub unsafe fn sfence_w_inval() {
-    // asm!("sfence.w.inval", options(nostack))
-    asm!(".insn i 0x73, 0, x0, x0, 0x180", options(nostack))
+    // asm!("sfence.w.inval", options(nostack, preserves_flags));
+    asm!(
+        ".insn i 0x73, 0, x0, x0, 0x180",
+        options(nostack, preserves_flags)
+    );
 }
 
 /// Generates the `SFENCE.INVAL.IR` instruction
@@ -191,8 +217,11 @@ pub unsafe fn sfence_w_inval() {
 #[inline]
 #[unstable(feature = "riscv_ext_intrinsics", issue = "114544")]
 pub unsafe fn sfence_inval_ir() {
-    // asm!("sfence.inval.ir", options(nostack))
-    asm!(".insn i 0x73, 0, x0, x0, 0x181", options(nostack))
+    // asm!("sfence.inval.ir", options(nostack, preserves_flags));
+    asm!(
+        ".insn i 0x73, 0, x0, x0, 0x181",
+        options(nostack, preserves_flags)
+    );
 }
 
 /// Loads virtual machine memory by signed byte integer
@@ -207,7 +236,12 @@ pub unsafe fn sfence_inval_ir() {
 #[unstable(feature = "riscv_ext_intrinsics", issue = "114544")]
 pub unsafe fn hlv_b(src: *const i8) -> i8 {
     let value: i8;
-    asm!(".insn i 0x73, 0x4, {}, {}, 0x600", out(reg) value, in(reg) src, options(readonly, nostack));
+    asm!(
+        ".insn i 0x73, 0x4, {}, {}, 0x600",
+        lateout(reg) value,
+        in(reg) src,
+        options(readonly, nostack, preserves_flags)
+    );
     value
 }
 
@@ -223,7 +257,12 @@ pub unsafe fn hlv_b(src: *const i8) -> i8 {
 #[unstable(feature = "riscv_ext_intrinsics", issue = "114544")]
 pub unsafe fn hlv_bu(src: *const u8) -> u8 {
     let value: u8;
-    asm!(".insn i 0x73, 0x4, {}, {}, 0x601", out(reg) value, in(reg) src, options(readonly, nostack));
+    asm!(
+        ".insn i 0x73, 0x4, {}, {}, 0x601",
+        lateout(reg) value,
+        in(reg) src,
+        options(readonly, nostack, preserves_flags)
+    );
     value
 }
 
@@ -239,7 +278,12 @@ pub unsafe fn hlv_bu(src: *const u8) -> u8 {
 #[unstable(feature = "riscv_ext_intrinsics", issue = "114544")]
 pub unsafe fn hlv_h(src: *const i16) -> i16 {
     let value: i16;
-    asm!(".insn i 0x73, 0x4, {}, {}, 0x640", out(reg) value, in(reg) src, options(readonly, nostack));
+    asm!(
+        ".insn i 0x73, 0x4, {}, {}, 0x640",
+        lateout(reg) value,
+        in(reg) src,
+        options(readonly, nostack, preserves_flags)
+    );
     value
 }
 
@@ -255,7 +299,12 @@ pub unsafe fn hlv_h(src: *const i16) -> i16 {
 #[unstable(feature = "riscv_ext_intrinsics", issue = "114544")]
 pub unsafe fn hlv_hu(src: *const u16) -> u16 {
     let value: u16;
-    asm!(".insn i 0x73, 0x4, {}, {}, 0x641", out(reg) value, in(reg) src, options(readonly, nostack));
+    asm!(
+        ".insn i 0x73, 0x4, {}, {}, 0x641",
+        lateout(reg) value,
+        in(reg) src,
+        options(readonly, nostack, preserves_flags)
+    );
     value
 }
 
@@ -271,7 +320,12 @@ pub unsafe fn hlv_hu(src: *const u16) -> u16 {
 #[unstable(feature = "riscv_ext_intrinsics", issue = "114544")]
 pub unsafe fn hlvx_hu(src: *const u16) -> u16 {
     let insn: u16;
-    asm!(".insn i 0x73, 0x4, {}, {}, 0x643", out(reg) insn, in(reg) src, options(readonly, nostack));
+    asm!(
+        ".insn i 0x73, 0x4, {}, {}, 0x643",
+        lateout(reg) insn,
+        in(reg) src,
+        options(readonly, nostack, preserves_flags)
+    );
     insn
 }
 
@@ -287,7 +341,12 @@ pub unsafe fn hlvx_hu(src: *const u16) -> u16 {
 #[unstable(feature = "riscv_ext_intrinsics", issue = "114544")]
 pub unsafe fn hlv_w(src: *const i32) -> i32 {
     let value: i32;
-    asm!(".insn i 0x73, 0x4, {}, {}, 0x680", out(reg) value, in(reg) src, options(readonly, nostack));
+    asm!(
+        ".insn i 0x73, 0x4, {}, {}, 0x680",
+        lateout(reg) value,
+        in(reg) src,
+        options(readonly, nostack, preserves_flags)
+    );
     value
 }
 
@@ -303,7 +362,12 @@ pub unsafe fn hlv_w(src: *const i32) -> i32 {
 #[unstable(feature = "riscv_ext_intrinsics", issue = "114544")]
 pub unsafe fn hlvx_wu(src: *const u32) -> u32 {
     let insn: u32;
-    asm!(".insn i 0x73, 0x4, {}, {}, 0x683", out(reg) insn, in(reg) src, options(readonly, nostack));
+    asm!(
+        ".insn i 0x73, 0x4, {}, {}, 0x683",
+        lateout(reg) insn,
+        in(reg) src,
+        options(readonly, nostack, preserves_flags)
+    );
     insn
 }
 
@@ -318,7 +382,12 @@ pub unsafe fn hlvx_wu(src: *const u32) -> u32 {
 #[inline]
 #[unstable(feature = "riscv_ext_intrinsics", issue = "114544")]
 pub unsafe fn hsv_b(dst: *mut i8, src: i8) {
-    asm!(".insn r 0x73, 0x4, 0x31, x0, {}, {}", in(reg) dst, in(reg) src, options(nostack));
+    asm!(
+        ".insn r 0x73, 0x4, 0x31, x0, {}, {}",
+        in(reg) dst,
+        in(reg) src,
+        options(nostack, preserves_flags)
+    );
 }
 
 /// Stores virtual machine memory by half integer
@@ -332,7 +401,12 @@ pub unsafe fn hsv_b(dst: *mut i8, src: i8) {
 #[inline]
 #[unstable(feature = "riscv_ext_intrinsics", issue = "114544")]
 pub unsafe fn hsv_h(dst: *mut i16, src: i16) {
-    asm!(".insn r 0x73, 0x4, 0x33, x0, {}, {}", in(reg) dst, in(reg) src, options(nostack));
+    asm!(
+        ".insn r 0x73, 0x4, 0x33, x0, {}, {}",
+        in(reg) dst,
+        in(reg) src,
+        options(nostack, preserves_flags)
+    );
 }
 
 /// Stores virtual machine memory by word integer
@@ -346,7 +420,12 @@ pub unsafe fn hsv_h(dst: *mut i16, src: i16) {
 #[inline]
 #[unstable(feature = "riscv_ext_intrinsics", issue = "114544")]
 pub unsafe fn hsv_w(dst: *mut i32, src: i32) {
-    asm!(".insn r 0x73, 0x4, 0x35, x0, {}, {}", in(reg) dst, in(reg) src, options(nostack));
+    asm!(
+        ".insn r 0x73, 0x4, 0x35, x0, {}, {}",
+        in(reg) dst,
+        in(reg) src,
+        options(nostack, preserves_flags)
+    );
 }
 
 /// Hypervisor memory management fence for given guest virtual address and guest address space
@@ -360,8 +439,13 @@ pub unsafe fn hsv_w(dst: *mut i32, src: i32) {
 #[inline]
 #[unstable(feature = "riscv_ext_intrinsics", issue = "114544")]
 pub unsafe fn hfence_vvma(vaddr: usize, asid: usize) {
-    // asm!("hfence.vvma {}, {}", in(reg) vaddr, in(reg) asid)
-    asm!(".insn r 0x73, 0, 0x11, x0, {}, {}", in(reg) vaddr, in(reg) asid, options(nostack))
+    // asm!("hfence.vvma {}, {}", in(reg) vaddr, in(reg) asid, options(nostack, preserves_flags));
+    asm!(
+        ".insn r 0x73, 0, 0x11, x0, {}, {}",
+        in(reg) vaddr,
+        in(reg) asid,
+        options(nostack, preserves_flags)
+    );
 }
 
 /// Hypervisor memory management fence for given guest virtual address
@@ -375,7 +459,11 @@ pub unsafe fn hfence_vvma(vaddr: usize, asid: usize) {
 #[inline]
 #[unstable(feature = "riscv_ext_intrinsics", issue = "114544")]
 pub unsafe fn hfence_vvma_vaddr(vaddr: usize) {
-    asm!(".insn r 0x73, 0, 0x11, x0, {}, x0", in(reg) vaddr, options(nostack))
+    asm!(
+        ".insn r 0x73, 0, 0x11, x0, {}, x0",
+        in(reg) vaddr,
+        options(nostack, preserves_flags)
+    );
 }
 
 /// Hypervisor memory management fence for given guest address space
@@ -389,7 +477,11 @@ pub unsafe fn hfence_vvma_vaddr(vaddr: usize) {
 #[inline]
 #[unstable(feature = "riscv_ext_intrinsics", issue = "114544")]
 pub unsafe fn hfence_vvma_asid(asid: usize) {
-    asm!(".insn r 0x73, 0, 0x11, x0, x0, {}", in(reg) asid, options(nostack))
+    asm!(
+        ".insn r 0x73, 0, 0x11, x0, x0, {}",
+        in(reg) asid,
+        options(nostack, preserves_flags)
+    );
 }
 
 /// Hypervisor memory management fence for all guest address spaces and guest virtual addresses
@@ -403,7 +495,10 @@ pub unsafe fn hfence_vvma_asid(asid: usize) {
 #[inline]
 #[unstable(feature = "riscv_ext_intrinsics", issue = "114544")]
 pub unsafe fn hfence_vvma_all() {
-    asm!(".insn r 0x73, 0, 0x11, x0, x0, x0", options(nostack))
+    asm!(
+        ".insn r 0x73, 0, 0x11, x0, x0, x0",
+        options(nostack, preserves_flags)
+    );
 }
 
 /// Hypervisor memory management fence for guest physical address and virtual machine
@@ -416,8 +511,13 @@ pub unsafe fn hfence_vvma_all() {
 #[inline]
 #[unstable(feature = "riscv_ext_intrinsics", issue = "114544")]
 pub unsafe fn hfence_gvma(gaddr: usize, vmid: usize) {
-    // asm!("hfence.gvma {}, {}", in(reg) gaddr, in(reg) vmid, options(nostack))
-    asm!(".insn r 0x73, 0, 0x31, x0, {}, {}", in(reg) gaddr, in(reg) vmid, options(nostack))
+    // asm!("hfence.gvma {}, {}", in(reg) gaddr, in(reg) vmid, options(nostack, preserves_flags));
+    asm!(
+        ".insn r 0x73, 0, 0x31, x0, {}, {}",
+        in(reg) gaddr,
+        in(reg) vmid,
+        options(nostack, preserves_flags)
+    );
 }
 
 /// Hypervisor memory management fence for guest physical address
@@ -429,7 +529,11 @@ pub unsafe fn hfence_gvma(gaddr: usize, vmid: usize) {
 #[inline]
 #[unstable(feature = "riscv_ext_intrinsics", issue = "114544")]
 pub unsafe fn hfence_gvma_gaddr(gaddr: usize) {
-    asm!(".insn r 0x73, 0, 0x31, x0, {}, x0", in(reg) gaddr, options(nostack))
+    asm!(
+        ".insn r 0x73, 0, 0x31, x0, {}, x0",
+        in(reg) gaddr,
+        options(nostack, preserves_flags)
+    );
 }
 
 /// Hypervisor memory management fence for given virtual machine
@@ -441,7 +545,11 @@ pub unsafe fn hfence_gvma_gaddr(gaddr: usize) {
 #[inline]
 #[unstable(feature = "riscv_ext_intrinsics", issue = "114544")]
 pub unsafe fn hfence_gvma_vmid(vmid: usize) {
-    asm!(".insn r 0x73, 0, 0x31, x0, x0, {}", in(reg) vmid, options(nostack))
+    asm!(
+        ".insn r 0x73, 0, 0x31, x0, x0, {}",
+        in(reg) vmid,
+        options(nostack, preserves_flags)
+    );
 }
 
 /// Hypervisor memory management fence for all virtual machines and guest physical addresses
@@ -453,7 +561,10 @@ pub unsafe fn hfence_gvma_vmid(vmid: usize) {
 #[inline]
 #[unstable(feature = "riscv_ext_intrinsics", issue = "114544")]
 pub unsafe fn hfence_gvma_all() {
-    asm!(".insn r 0x73, 0, 0x31, x0, x0, x0", options(nostack))
+    asm!(
+        ".insn r 0x73, 0, 0x31, x0, x0, x0",
+        options(nostack, preserves_flags)
+    );
 }
 
 /// Invalidate hypervisor translation cache for given guest virtual address and guest address space
@@ -465,8 +576,13 @@ pub unsafe fn hfence_gvma_all() {
 #[inline]
 #[unstable(feature = "riscv_ext_intrinsics", issue = "114544")]
 pub unsafe fn hinval_vvma(vaddr: usize, asid: usize) {
-    // asm!("hinval.vvma {}, {}", in(reg) vaddr, in(reg) asid, options(nostack))
-    asm!(".insn r 0x73, 0, 0x13, x0, {}, {}", in(reg) vaddr, in(reg) asid, options(nostack))
+    // asm!("hinval.vvma {}, {}", in(reg) vaddr, in(reg) asid, options(nostack, preserves_flags));
+    asm!(
+        ".insn r 0x73, 0, 0x13, x0, {}, {}",
+        in(reg) vaddr,
+        in(reg) asid,
+        options(nostack, preserves_flags)
+    );
 }
 
 /// Invalidate hypervisor translation cache for given guest virtual address
@@ -478,7 +594,11 @@ pub unsafe fn hinval_vvma(vaddr: usize, asid: usize) {
 #[inline]
 #[unstable(feature = "riscv_ext_intrinsics", issue = "114544")]
 pub unsafe fn hinval_vvma_vaddr(vaddr: usize) {
-    asm!(".insn r 0x73, 0, 0x13, x0, {}, x0", in(reg) vaddr, options(nostack))
+    asm!(
+        ".insn r 0x73, 0, 0x13, x0, {}, x0",
+        in(reg) vaddr,
+        options(nostack, preserves_flags)
+    );
 }
 
 /// Invalidate hypervisor translation cache for given guest address space
@@ -490,7 +610,11 @@ pub unsafe fn hinval_vvma_vaddr(vaddr: usize) {
 #[inline]
 #[unstable(feature = "riscv_ext_intrinsics", issue = "114544")]
 pub unsafe fn hinval_vvma_asid(asid: usize) {
-    asm!(".insn r 0x73, 0, 0x13, x0, x0, {}", in(reg) asid, options(nostack))
+    asm!(
+        ".insn r 0x73, 0, 0x13, x0, x0, {}",
+        in(reg) asid,
+        options(nostack, preserves_flags)
+    );
 }
 
 /// Invalidate hypervisor translation cache for all guest address spaces and guest virtual addresses
@@ -502,7 +626,10 @@ pub unsafe fn hinval_vvma_asid(asid: usize) {
 #[inline]
 #[unstable(feature = "riscv_ext_intrinsics", issue = "114544")]
 pub unsafe fn hinval_vvma_all() {
-    asm!(".insn r 0x73, 0, 0x13, x0, x0, x0", options(nostack))
+    asm!(
+        ".insn r 0x73, 0, 0x13, x0, x0, x0",
+        options(nostack, preserves_flags)
+    );
 }
 
 /// Invalidate hypervisor translation cache for guest physical address and virtual machine
@@ -515,8 +642,13 @@ pub unsafe fn hinval_vvma_all() {
 #[inline]
 #[unstable(feature = "riscv_ext_intrinsics", issue = "114544")]
 pub unsafe fn hinval_gvma(gaddr: usize, vmid: usize) {
-    // asm!("hinval.gvma {}, {}", in(reg) gaddr, in(reg) vmid, options(nostack))
-    asm!(".insn r 0x73, 0, 0x33, x0, {}, {}", in(reg) gaddr, in(reg) vmid, options(nostack))
+    // asm!("hinval.gvma {}, {}", in(reg) gaddr, in(reg) vmid, options(nostack, preserves_flags));
+    asm!(
+        ".insn r 0x73, 0, 0x33, x0, {}, {}",
+        in(reg) gaddr,
+        in(reg) vmid,
+        options(nostack, preserves_flags)
+    );
 }
 
 /// Invalidate hypervisor translation cache for guest physical address
@@ -528,7 +660,11 @@ pub unsafe fn hinval_gvma(gaddr: usize, vmid: usize) {
 #[inline]
 #[unstable(feature = "riscv_ext_intrinsics", issue = "114544")]
 pub unsafe fn hinval_gvma_gaddr(gaddr: usize) {
-    asm!(".insn r 0x73, 0, 0x33, x0, {}, x0", in(reg) gaddr, options(nostack))
+    asm!(
+        ".insn r 0x73, 0, 0x33, x0, {}, x0",
+        in(reg) gaddr,
+        options(nostack, preserves_flags)
+    );
 }
 
 /// Invalidate hypervisor translation cache for given virtual machine
@@ -540,7 +676,11 @@ pub unsafe fn hinval_gvma_gaddr(gaddr: usize) {
 #[inline]
 #[unstable(feature = "riscv_ext_intrinsics", issue = "114544")]
 pub unsafe fn hinval_gvma_vmid(vmid: usize) {
-    asm!(".insn r 0x73, 0, 0x33, x0, x0, {}", in(reg) vmid, options(nostack))
+    asm!(
+        ".insn r 0x73, 0, 0x33, x0, x0, {}",
+        in(reg) vmid,
+        options(nostack, preserves_flags)
+    );
 }
 
 /// Invalidate hypervisor translation cache for all virtual machines and guest physical addresses
@@ -552,7 +692,10 @@ pub unsafe fn hinval_gvma_vmid(vmid: usize) {
 #[inline]
 #[unstable(feature = "riscv_ext_intrinsics", issue = "114544")]
 pub unsafe fn hinval_gvma_all() {
-    asm!(".insn r 0x73, 0, 0x33, x0, x0, x0", options(nostack))
+    asm!(
+        ".insn r 0x73, 0, 0x33, x0, x0, x0",
+        options(nostack, preserves_flags)
+    );
 }
 
 /// Reads the floating-point rounding mode register `frm`
@@ -574,6 +717,12 @@ pub unsafe fn hinval_gvma_all() {
 #[unstable(feature = "riscv_ext_intrinsics", issue = "114544")]
 pub fn frrm() -> u32 {
     let value: u32;
-    unsafe { asm!("frrm {}", out(reg) value, options(nomem, nostack)) };
+    unsafe {
+        asm!(
+            "frrm {}",
+            out(reg) value,
+            options(nomem, nostack, preserves_flags)
+        );
+    }
     value
 }