Skip to content

Commit 61fb16a

Browse files
authored
Merge pull request #40 from manchangfengxu/feat/extension
refactor: use bitflags-based Extensions for RISC-V decoder
2 parents 70efc2a + e5b66d4 commit 61fb16a

File tree

14 files changed

+229
-164
lines changed

14 files changed

+229
-164
lines changed

Cargo.lock

Lines changed: 7 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

robustone-core/Cargo.toml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ edition = "2024"
55

66
[dependencies]
77
hex = "0.4"
8+
bitflags = "2.10.0"
89

910
[features]
1011
default = ["riscv"]

robustone-core/src/riscv/decoder.rs

Lines changed: 13 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,8 @@
44
//! is implemented as a separate module, making the codebase more maintainable
55
//! and easier to extend with new instructions.
66
7-
use super::extensions::{InstructionExtension, create_extensions, extension_masks};
7+
use super::extensions::standard::Standard;
8+
use super::extensions::{Extensions, InstructionExtension, create_extensions};
89
use super::types::*;
910
use crate::error::DisasmError;
1011

@@ -19,13 +20,13 @@ pub enum Xlen {
1920
/// Refactored RISC-V instruction decoder using extension modules.
2021
pub struct RiscVDecoder {
2122
xlen: Xlen,
22-
extensions: u32,
23+
extensions: Extensions,
2324
extension_handlers: Vec<Box<dyn InstructionExtension>>,
2425
}
2526

2627
impl RiscVDecoder {
2728
/// Construct a decoder with the provided XLEN and extension bitmask.
28-
pub fn new(xlen: Xlen, extensions: u32) -> Self {
29+
pub fn new(xlen: Xlen, extensions: Extensions) -> Self {
2930
let extension_handlers = create_extensions();
3031
Self {
3132
xlen,
@@ -36,28 +37,12 @@ impl RiscVDecoder {
3637

3738
/// Create a decoder with full RV32GC support.
3839
pub fn rv32gc() -> Self {
39-
Self::new(
40-
Xlen::X32,
41-
extension_masks::I
42-
| extension_masks::M
43-
| extension_masks::A
44-
| extension_masks::F
45-
| extension_masks::C
46-
| extension_masks::XTHEADCONDMOV,
47-
)
40+
Self::new(Xlen::X32, Extensions::rv32gc())
4841
}
4942

5043
/// Create a decoder with full RV64GC support.
5144
pub fn rv64gc() -> Self {
52-
Self::new(
53-
Xlen::X64,
54-
extension_masks::I
55-
| extension_masks::M
56-
| extension_masks::A
57-
| extension_masks::F
58-
| extension_masks::D
59-
| extension_masks::C,
60-
)
45+
Self::new(Xlen::X64, Extensions::rv64gc())
6146
}
6247

6348
/// Decode a single instruction located at `address`.
@@ -131,7 +116,7 @@ impl RiscVDecoder {
131116

132117
// Try each enabled extension in order
133118
for extension in &self.extension_handlers {
134-
if !extension.is_enabled(self.extensions) {
119+
if !extension.is_enabled(&self.extensions) {
135120
continue;
136121
}
137122

@@ -229,13 +214,13 @@ impl RiscVDecoder {
229214
| ((instruction >> 6) & 0x1) << 6 // imm[6] from instruction[6]
230215
| ((instruction >> 9) & 0x3) << 7; // imm[8:7] from instruction[9:8]
231216

232-
if self.extensions & extension_masks::C == 0 {
217+
if !self.extensions.standard.contains(Standard::C) {
233218
eprintln!("Warning: Decoding compressed instruction while C extension is disabled");
234219
}
235220

236221
// Try each enabled extension for compressed instructions
237222
for extension in &self.extension_handlers {
238-
if !extension.is_enabled(self.extensions) {
223+
if !extension.is_enabled(&self.extensions) {
239224
continue;
240225
}
241226

@@ -334,20 +319,16 @@ mod tests {
334319
fn test_refactored_decoder_creation() {
335320
let decoder = RiscVDecoder::rv32gc();
336321
assert_eq!(decoder.xlen, Xlen::X32);
337-
assert!(decoder.extensions & extension_masks::I != 0);
322+
assert!(decoder.extensions.standard.contains(Standard::I));
338323

339324
let decoder = RiscVDecoder::rv64gc();
340325
assert_eq!(decoder.xlen, Xlen::X64);
341-
assert!(decoder.extensions & extension_masks::I != 0);
326+
assert!(decoder.extensions.standard.contains(Standard::I));
342327

343328
let decoder = RiscVDecoder::rv64gc();
344329
assert_eq!(decoder.xlen, Xlen::X64);
345-
assert!(decoder.extensions & extension_masks::I != 0);
346-
assert!(decoder.extensions & extension_masks::M != 0);
347-
assert!(decoder.extensions & extension_masks::A != 0);
348-
assert!(decoder.extensions & extension_masks::F != 0);
349-
assert!(decoder.extensions & extension_masks::D != 0);
350-
assert!(decoder.extensions & extension_masks::C != 0);
330+
assert!(decoder.extensions.standard.contains(Standard::G));
331+
assert!(decoder.extensions.standard.contains(Standard::C));
351332
}
352333

353334
#[test]

robustone-core/src/riscv/extensions/mod.rs

Lines changed: 47 additions & 38 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,45 @@
66
use super::decoder::{RiscVDecodedInstruction, Xlen};
77
use crate::error::DisasmError;
88

9+
// Submodules grouping standard and custom-specific extensions.
10+
pub mod standard;
11+
pub mod thead;
12+
13+
use standard::Standard;
14+
use thead::THead;
15+
16+
/// Aggregated extension configuration passed to RISC-V extension handlers.
17+
pub struct Extensions {
18+
pub(crate) standard: Standard,
19+
pub(crate) thead: THead,
20+
}
21+
22+
impl Extensions {
23+
/// Convenience configuration for RV32GC profile with all standard and
24+
/// no T-Head custom extensions enabled.
25+
pub fn rv32gc() -> Self {
26+
Self {
27+
standard: Standard::G | Standard::C,
28+
thead: THead::empty(),
29+
}
30+
}
31+
32+
/// Convenience configuration for RV64GC profile with all standard and
33+
/// no T-Head custom extensions enabled.
34+
pub fn rv64gc() -> Self {
35+
Self {
36+
standard: Standard::G | Standard::C,
37+
thead: THead::empty(),
38+
}
39+
}
40+
41+
/// Enables all available T-Head custom extensions on this configuration.
42+
pub fn thead(mut self) -> Self {
43+
self.thead |= THead::all();
44+
self
45+
}
46+
}
47+
948
/// Trait that all instruction set extensions must implement.
1049
#[allow(clippy::too_many_arguments)]
1150
pub trait InstructionExtension: Sync {
@@ -65,48 +104,18 @@ pub trait InstructionExtension: Sync {
65104
fn name(&self) -> &'static str;
66105

67106
/// Check if this extension is enabled for the given configuration.
68-
fn is_enabled(&self, extensions: u32) -> bool;
107+
fn is_enabled(&self, extensions: &Extensions) -> bool;
69108
}
70109

71-
// Standard RISC-V extension modules
72-
pub mod rva; // RVA - Atomic Instructions
73-
pub mod rvc; // RVC - Compressed Instructions
74-
pub mod rvd; // RVD - Double-Precision Floating-Point
75-
pub mod rvf; // RVF - Single-Precision Floating-Point
76-
pub mod rvi; // RV32I/RV64I - Base Integer Instruction Set
77-
pub mod rvm; // RVM - Multiply and Divide Instructions
78-
79-
// XuanTie vendor extension modules
80-
pub mod xtheadcondmov; // XTheadCondMov - Conditional Move Instructions
81-
82-
use rva::RvaExtension;
83-
use rvc::RvcExtension;
84-
use rvd::RvdExtension;
85-
use rvf::RvfExtension;
86-
use rvi::RviExtension;
87-
use rvm::RvmExtension;
88-
use xtheadcondmov::XTheadCondMovExtension;
89-
90110
/// Create all available standard RISC-V extensions.
91111
pub fn create_extensions() -> Vec<Box<dyn InstructionExtension>> {
92112
vec![
93-
Box::new(RviExtension::new()),
94-
Box::new(RvaExtension::new()),
95-
Box::new(RvmExtension::new()),
96-
Box::new(RvfExtension::new()),
97-
Box::new(RvdExtension::new()),
98-
Box::new(RvcExtension::new()),
99-
Box::new(XTheadCondMovExtension::new()),
113+
Box::new(standard::Rvi::new()),
114+
Box::new(standard::Rva::new()),
115+
Box::new(standard::Rvm::new()),
116+
Box::new(standard::Rvf::new()),
117+
Box::new(standard::Rvd::new()),
118+
Box::new(standard::Rvc::new()),
119+
Box::new(thead::CMov::new()),
100120
]
101121
}
102-
103-
/// Extension bit masks for standard RISC-V and XuanTie extensions.
104-
pub mod extension_masks {
105-
pub const I: u32 = 0b001; // Base Integer Instruction Set
106-
pub const M: u32 = 0b010; // Multiply and Divide
107-
pub const A: u32 = 0b100; // Atomic Instructions
108-
pub const F: u32 = 0b1000; // Single-Precision Floating-Point
109-
pub const D: u32 = 0b10000; // Double-Precision Floating-Point
110-
pub const C: u32 = 0b100000; // Compressed Instructions
111-
pub const XTHEADCONDMOV: u32 = 0b1000000; // XTheadCondMov - Conditional Move
112-
}
Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
1+
//! Standard RISC-V extensions and configuration.
2+
//!
3+
//! This module defines the `StandardExtensions` bitflags for core RISC-V
4+
//! extensions (I/M/A/F/D/C) and re-exports the corresponding extension
5+
//! handler types under the `standard` namespace.
6+
7+
use bitflags::bitflags;
8+
9+
pub mod rva;
10+
pub mod rvc;
11+
pub mod rvd;
12+
pub mod rvf;
13+
pub mod rvi;
14+
pub mod rvm;
15+
16+
pub use rva::Rva;
17+
pub use rvc::Rvc;
18+
pub use rvd::Rvd;
19+
pub use rvf::Rvf;
20+
pub use rvi::Rvi;
21+
pub use rvm::Rvm;
22+
23+
bitflags! {
24+
/// Bitflags representing enabled standard RISC-V extensions.
25+
pub struct Standard: u32 {
26+
const I = 1;
27+
const M = 1 << 1;
28+
const A = 1 << 2;
29+
const F = 1 << 3;
30+
const D = 1 << 4;
31+
const C = 1 << 5;
32+
/// Shorthand for the standard G profile (IMAFD).
33+
const G = Self::I.bits()
34+
| Self::M.bits()
35+
| Self::A.bits()
36+
| Self::F.bits()
37+
| Self::D.bits();
38+
}
39+
}

robustone-core/src/riscv/extensions/rva.rs renamed to robustone-core/src/riscv/extensions/standard/rva.rs

Lines changed: 12 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -3,22 +3,22 @@
33
//! This module implements the RISC-V atomic instructions extension (A extension),
44
//! which provides atomic memory operations for synchronization and concurrency.
55
6-
use super::super::decoder::{RiscVDecodedInstruction, Xlen};
7-
use super::super::shared::{
6+
use super::Standard;
7+
use crate::error::DisasmError;
8+
use crate::riscv::decoder::{RiscVDecodedInstruction, Xlen};
9+
use crate::riscv::extensions::{Extensions, InstructionExtension};
10+
use crate::riscv::shared::{
811
operands::convenience,
912
registers::{RegisterManager, RegisterNameProvider},
1013
};
11-
use super::super::types::*;
12-
use super::InstructionExtension;
13-
use crate::error::DisasmError;
14-
use crate::riscv::extensions::extension_masks;
14+
use crate::riscv::types::*;
1515

1616
/// RVA Atomic Instructions Extension
17-
pub struct RvaExtension {
17+
pub struct Rva {
1818
register_manager: RegisterManager,
1919
}
2020

21-
impl RvaExtension {
21+
impl Rva {
2222
/// Create a new RVA extension instance.
2323
pub fn new() -> Self {
2424
Self {
@@ -111,14 +111,14 @@ impl RvaExtension {
111111
}
112112
}
113113

114-
impl InstructionExtension for RvaExtension {
114+
impl InstructionExtension for Rva {
115115
fn name(&self) -> &'static str {
116116
"A"
117117
}
118118

119-
fn is_enabled(&self, extensions: u32) -> bool {
119+
fn is_enabled(&self, extensions: &Extensions) -> bool {
120120
// A extension bit (bit 2)
121-
extensions & extension_masks::A != 0
121+
extensions.standard.contains(Standard::A)
122122
}
123123

124124
fn try_decode_standard(
@@ -250,7 +250,7 @@ impl InstructionExtension for RvaExtension {
250250
}
251251
}
252252

253-
impl Default for RvaExtension {
253+
impl Default for Rva {
254254
fn default() -> Self {
255255
Self::new()
256256
}

robustone-core/src/riscv/extensions/rvc.rs renamed to robustone-core/src/riscv/extensions/standard/rvc.rs

Lines changed: 12 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -3,23 +3,23 @@
33
//! This module implements the RISC-V compressed instruction extension (C extension),
44
//! which provides 16-bit compressed versions of common instructions to improve code density.
55
6-
use super::super::decoder::{RiscVDecodedInstruction, Xlen};
7-
use super::super::shared::{
6+
use super::Standard;
7+
use crate::error::DisasmError;
8+
use crate::riscv::decoder::{RiscVDecodedInstruction, Xlen};
9+
use crate::riscv::extensions::{Extensions, InstructionExtension};
10+
use crate::riscv::shared::{
811
encoding::convenience as encoding_conv,
912
operands::convenience,
1013
registers::{RegisterManager, RegisterNameProvider},
1114
};
12-
use super::super::types::*;
13-
use super::InstructionExtension;
14-
use crate::error::DisasmError;
15-
use crate::riscv::extensions::extension_masks;
15+
use crate::riscv::types::*;
1616

1717
/// RVC Compressed Instructions Extension
18-
pub struct RvcExtension {
18+
pub struct Rvc {
1919
register_manager: RegisterManager,
2020
}
2121

22-
impl RvcExtension {
22+
impl Rvc {
2323
/// Create a new RVC extension instance.
2424
pub fn new() -> Self {
2525
Self {
@@ -366,14 +366,14 @@ impl RvcExtension {
366366
}
367367
}
368368

369-
impl InstructionExtension for RvcExtension {
369+
impl InstructionExtension for Rvc {
370370
fn name(&self) -> &'static str {
371371
"C"
372372
}
373373

374-
fn is_enabled(&self, extensions: u32) -> bool {
374+
fn is_enabled(&self, extensions: &Extensions) -> bool {
375375
// C extension bit (bit 5)
376-
extensions & extension_masks::C != 0
376+
extensions.standard.contains(Standard::C)
377377
}
378378

379379
fn try_decode_standard(
@@ -472,7 +472,7 @@ impl InstructionExtension for RvcExtension {
472472
}
473473
}
474474

475-
impl Default for RvcExtension {
475+
impl Default for Rvc {
476476
fn default() -> Self {
477477
Self::new()
478478
}

0 commit comments

Comments
 (0)