Skip to content
Merged
Show file tree
Hide file tree
Changes from 2 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
17 changes: 16 additions & 1 deletion riscv/CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,20 @@ and this project adheres to [Semantic Versioning](http://semver.org/).

## [Unreleased]

- Improved assembly macro handling in asm.rs

### Added

- Add `miselect` CSR

## [v0.15.0] - 2025-09-08


### Added

- Add `miselect` CSR
- Improved assembly macro handling in asm.rs

### Added

- Add `miselect` CSR
Expand Down Expand Up @@ -116,6 +130,7 @@ and this project adheres to [Semantic Versioning](http://semver.org/).
- Export `riscv::register::macros` module macros for external use
- Add `riscv::register::mcountinhibit` module for `mcountinhibit` CSR
- Add `Mcounteren` in-memory update functions
- Add `Mcounteren` in-memory update functions
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This changelog line is still duplicated.
As previously requested, please fix this.

Before you request someone to review your code, please use the review tools to check the work yourself.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hi @9names

Apologies for the inconvenience earlier with the CHANGELOG. I’ve cleaned things up by:

  • Removing the duplicate v0.15.0 section

  • Consolidating all the fixes into a single, neat commit

  • Ensuring the CHANGELOG is consistent and conflict-free

Thank you for your patience — the PR should now be ready for review.

- Add `Mstatus` vector extension support
- Add fallible counterparts to all functions that `panic`
- Add `riscv-pac` as a dependency
Expand Down Expand Up @@ -283,4 +298,4 @@ and this project adheres to [Semantic Versioning](http://semver.org/).
[v0.7.0]: https://github.com/rust-embedded/riscv/compare/v0.6.0...v0.7.0
[v0.6.0]: https://github.com/rust-embedded/riscv/compare/v0.5.6...v0.6.0
[v0.5.6]: https://github.com/rust-embedded/riscv/compare/v0.5.5...v0.5.6
[v0.5.5]: https://github.com/rust-embedded/riscv/compare/v0.5.4...v0.5.5
[v0.5.5]: https://github.com/rust-embedded/riscv/compare/v0.5.4...v0.5.5
81 changes: 52 additions & 29 deletions riscv/src/asm.rs
Original file line number Diff line number Diff line change
Expand Up @@ -20,45 +20,70 @@ macro_rules! instruction {
#[cfg(not(any(target_arch = "riscv32", target_arch = "riscv64")))]
unimplemented!();
}
);
)
}

instruction!(
/// `nop` instruction wrapper
/// `NOP` instruction wrapper
///
/// The `NOP` instruction does not change any architecturally visible state, except for
/// advancing the pc and incrementing any applicable performance counters.
/// advancing the PC and incrementing any applicable performance counters.
///
/// This function generates a no-operation; it's useful to prevent delay loops from being
/// optimized away.
, nop, "nop", options(nomem, nostack));
, nop, "nop", options(nomem, nostack, preserves_flags));

instruction!(
/// `WFI` instruction wrapper
///
/// Provides a hint to the implementation that the current hart can be stalled until an interrupt might need servicing.
/// The WFI instruction is just a hint, and a legal implementation is to implement WFI as a NOP.
, wfi, "wfi", options(nomem, nostack));
/// Provides a hint to the implementation that the current hart can be stalled until an
/// interrupt might need servicing. The WFI instruction is just a hint, and a legal
/// implementation is to implement WFI as a NOP.
///
/// # Behavior
///
/// - May cause the hart to enter a low-power state
/// - Will be interrupted by any enabled interrupt
/// - No guarantee of actual power savings (implementation-dependent)
,wfi, "wfi", options(nomem, nostack, preserves_flags));

instruction!(
/// `EBREAK` instruction wrapper
///
/// Generates a breakpoint exception.
, unsafe ebreak, "ebreak", options(nomem, nostack));
/// Generates a breakpoint exception for use by debuggers.
///
/// # Behavior
///
/// When executed, this instruction causes a breakpoint exception to be raised,
/// which will typically be handled by a debugger or exception handler.
///
/// # Safety
///
/// This function is unsafe because it unconditionally generates an exception,
/// which can disrupt normal program flow. Only call this when you intend to
/// trigger a breakpoint.
, unsafe ebreak, "ebreak", options(nomem, nostack, preserves_flags));

instruction!(
/// `ECALL` instruction wrapper
///
/// Generates an exception for a service request to the execution environment.
/// When executed in U-mode, S-mode, or M-mode, it generates an environment-call-from-U-mode
/// exception, environment-call-from-S-mode exception, or environment-call-from-M-mode exception,
/// respectively, and performs no other operation.
/// Generates an environment call exception for system services.
///
/// # Note
/// # Behavior
///
/// The ECALL instruction will **NOT** save and restore the stack pointer, as it triggers an exception.
/// The stack pointer must be saved and restored accordingly by the exception handler.
, unsafe ecall, "ecall", options(nomem, nostack));
/// When executed in different privilege modes:
/// - U-mode: Generates environment-call-from-U-mode exception
/// - S-mode: Generates environment-call-from-S-mode exception
/// - M-mode: Generates environment-call-from-M-mode exception
///
/// # Safety
///
/// This function is unsafe because:
/// - It unconditionally generates an exception
/// - The stack pointer is **NOT** automatically saved/restored
/// - The exception handler is responsible for proper context management
/// - Improper use can crash the system
, unsafe ecall, "ecall", options(nomem, nostack, preserves_flags));

instruction!(
/// `SFENCE.VMA` instruction wrapper (all address spaces and page table levels)
Expand Down Expand Up @@ -118,8 +143,8 @@ instruction!(
pub fn sfence_vma(asid: usize, addr: usize) {
#[cfg(any(target_arch = "riscv32", target_arch = "riscv64"))]
unsafe {
core::arch::asm!("sfence.vma {0}, {1}", in(reg) addr, in(reg) asid, options(nostack));
};
core::arch::asm!("sfence.vma {}, {}", in(reg) addr, in(reg) asid, options(nostack));
}
#[cfg(not(any(target_arch = "riscv32", target_arch = "riscv64")))]
unimplemented!();
}
Expand All @@ -139,21 +164,19 @@ pub fn sfence_vma(asid: usize, addr: usize) {
allow(unused_variables)
)]
pub fn delay(cycles: u32) {
match () {
#[cfg(any(target_arch = "riscv32", target_arch = "riscv64"))]
() => {
let real_cyc = 1 + cycles / 2;
unsafe {
core::arch::asm!(
#[cfg(any(target_arch = "riscv32", target_arch = "riscv64"))]
{
let real_cyc = 1 + cycles / 2;
unsafe {
core::arch::asm!(
"2:",
"addi {0}, {0}, -1",
"bne {0}, zero, 2b",
inout(reg) real_cyc => _,
options(nomem, nostack),
);
}
);
}
#[cfg(not(any(target_arch = "riscv32", target_arch = "riscv64")))]
() => unimplemented!(),
}
#[cfg(not(any(target_arch = "riscv32", target_arch = "riscv64")))]
unimplemented!();
}
Loading