Skip to content

Commit 18cc082

Browse files
Merge pull request #341 from KushalMeghani1644/improvement
asm: Improve documentation and code quality for RISC-V instructions
2 parents c0cbc1c + a5ac148 commit 18cc082

File tree

2 files changed

+53
-29
lines changed

2 files changed

+53
-29
lines changed

riscv/CHANGELOG.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@ and this project adheres to [Semantic Versioning](http://semver.org/).
1010
### Added
1111

1212
- Add `miselect` CSR
13+
- Improved assembly macro handling in asm.rs
1314

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

riscv/src/asm.rs

Lines changed: 52 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -20,45 +20,70 @@ macro_rules! instruction {
2020
#[cfg(not(any(target_arch = "riscv32", target_arch = "riscv64")))]
2121
unimplemented!();
2222
}
23-
);
23+
)
2424
}
2525

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

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

4350
instruction!(
4451
/// `EBREAK` instruction wrapper
4552
///
46-
/// Generates a breakpoint exception.
47-
, unsafe ebreak, "ebreak", options(nomem, nostack));
53+
/// Generates a breakpoint exception for use by debuggers.
54+
///
55+
/// # Behavior
56+
///
57+
/// When executed, this instruction causes a breakpoint exception to be raised,
58+
/// which will typically be handled by a debugger or exception handler.
59+
///
60+
/// # Safety
61+
///
62+
/// This function is unsafe because it unconditionally generates an exception,
63+
/// which can disrupt normal program flow. Only call this when you intend to
64+
/// trigger a breakpoint.
65+
, unsafe ebreak, "ebreak", options(nomem, nostack, preserves_flags));
4866

4967
instruction!(
5068
/// `ECALL` instruction wrapper
5169
///
52-
/// Generates an exception for a service request to the execution environment.
53-
/// When executed in U-mode, S-mode, or M-mode, it generates an environment-call-from-U-mode
54-
/// exception, environment-call-from-S-mode exception, or environment-call-from-M-mode exception,
55-
/// respectively, and performs no other operation.
70+
/// Generates an environment call exception for system services.
5671
///
57-
/// # Note
72+
/// # Behavior
5873
///
59-
/// The ECALL instruction will **NOT** save and restore the stack pointer, as it triggers an exception.
60-
/// The stack pointer must be saved and restored accordingly by the exception handler.
61-
, unsafe ecall, "ecall", options(nomem, nostack));
74+
/// When executed in different privilege modes:
75+
/// - U-mode: Generates environment-call-from-U-mode exception
76+
/// - S-mode: Generates environment-call-from-S-mode exception
77+
/// - M-mode: Generates environment-call-from-M-mode exception
78+
///
79+
/// # Safety
80+
///
81+
/// This function is unsafe because:
82+
/// - It unconditionally generates an exception
83+
/// - The stack pointer is **NOT** automatically saved/restored
84+
/// - The exception handler is responsible for proper context management
85+
/// - Improper use can crash the system
86+
, unsafe ecall, "ecall", options(nomem, nostack, preserves_flags));
6287

6388
instruction!(
6489
/// `SFENCE.VMA` instruction wrapper (all address spaces and page table levels)
@@ -118,8 +143,8 @@ instruction!(
118143
pub fn sfence_vma(asid: usize, addr: usize) {
119144
#[cfg(any(target_arch = "riscv32", target_arch = "riscv64"))]
120145
unsafe {
121-
core::arch::asm!("sfence.vma {0}, {1}", in(reg) addr, in(reg) asid, options(nostack));
122-
};
146+
core::arch::asm!("sfence.vma {}, {}", in(reg) addr, in(reg) asid, options(nostack));
147+
}
123148
#[cfg(not(any(target_arch = "riscv32", target_arch = "riscv64")))]
124149
unimplemented!();
125150
}
@@ -139,21 +164,19 @@ pub fn sfence_vma(asid: usize, addr: usize) {
139164
allow(unused_variables)
140165
)]
141166
pub fn delay(cycles: u32) {
142-
match () {
143-
#[cfg(any(target_arch = "riscv32", target_arch = "riscv64"))]
144-
() => {
145-
let real_cyc = 1 + cycles / 2;
146-
unsafe {
147-
core::arch::asm!(
167+
#[cfg(any(target_arch = "riscv32", target_arch = "riscv64"))]
168+
{
169+
let real_cyc = 1 + cycles / 2;
170+
unsafe {
171+
core::arch::asm!(
148172
"2:",
149173
"addi {0}, {0}, -1",
150174
"bne {0}, zero, 2b",
151175
inout(reg) real_cyc => _,
152176
options(nomem, nostack),
153-
);
154-
}
177+
);
155178
}
156-
#[cfg(not(any(target_arch = "riscv32", target_arch = "riscv64")))]
157-
() => unimplemented!(),
158179
}
180+
#[cfg(not(any(target_arch = "riscv32", target_arch = "riscv64")))]
181+
unimplemented!();
159182
}

0 commit comments

Comments
 (0)