1pub const STANDARD_EXTENSIONS: [(&char, &str, &str); 11] = [
5 (&'i', "I", "Base Integer Instructions"),
6 (&'e', "E", "Embedded (16 registers)"),
7 (&'m', "M", "Integer Multiply/Divide"),
8 (&'a', "A", "Atomic Instructions"),
9 (&'f', "F", "Single-Precision Float"),
10 (&'d', "D", "Double-Precision Float"),
11 (&'q', "Q", "Quad-Precision Float"),
12 (&'c', "C", "Compressed (16-bit)"),
13 (&'b', "B", "Bit Manipulation"),
14 (&'v', "V", "Vector (SIMD)"),
15 (&'h', "H", "Hypervisor"),
16];
17
18pub const Z_EXTENSIONS: [(&str, &str, &str); 38] = [
20 ("zicsr", "Zicsr", "CSR Instructions"),
21 ("zifencei", "Zifencei", "Instruction-Fetch Fence"),
22 ("zicntr", "Zicntr", "Base Counters/Timers"),
23 ("zihpm", "Zihpm", "Hardware Perf Counters"),
24 ("zicbom", "Zicbom", "Cache-Block Management"),
25 ("zicboz", "Zicboz", "Cache-Block Zero"),
26 ("zicond", "Zicond", "Conditional Operations"),
27 ("zihintpause", "Zihintpause", "Pause Hint"),
28 ("zba", "Zba", "Address Generation"),
29 ("zbb", "Zbb", "Basic Bit Manipulation"),
30 ("zbc", "Zbc", "Carry-less Multiply"),
31 ("zbs", "Zbs", "Single-bit Operations"),
32 ("zbkb", "Zbkb", "Bit Manip for Crypto"),
33 ("zbkc", "Zbkc", "Carry-less for Crypto"),
34 ("zbkx", "Zbkx", "Crossbar for Crypto"),
35 ("zfh", "Zfh", "Half-Precision Float"),
36 ("zfhmin", "Zfhmin", "Minimal Half-Precision"),
37 ("zkt", "Zkt", "Constant-Time Execution"),
38 ("zca", "Zca", "Compressed Base"),
39 ("zcb", "Zcb", "Compressed Basic Ops"),
40 ("zcd", "Zcd", "Compressed Double FP"),
41 ("zcf", "Zcf", "Compressed Single FP"),
42 ("zve32f", "Zve32f", "Vector 32-bit Float"),
43 ("zve32x", "Zve32x", "Vector 32-bit Int"),
44 ("zve64d", "Zve64d", "Vector 64-bit Double"),
45 ("zve64f", "Zve64f", "Vector 64-bit Float"),
46 ("zve64x", "Zve64x", "Vector 64-bit Int"),
47 ("zvfh", "Zvfh", "Vector Half-Precision"),
48 ("zvfhmin", "Zvfhmin", "Min Vector Half-Prec"),
49 ("zvkt", "Zvkt", "Vector Constant-Time"),
50 ("zvl128b", "Zvl128b", "VLEN >= 128 bits"),
51 ("zvl256b", "Zvl256b", "VLEN >= 256 bits"),
52 ("zvl512b", "Zvl512b", "VLEN >= 512 bits"),
53 ("svinval", "Svinval", "Fine-Grained TLB"),
54 ("svnapot", "Svnapot", "NAPOT Translation"),
55 ("svpbmt", "Svpbmt", "Page-Based Mem Types"),
56 ("sscofpmf", "Sscofpmf", "Count Overflow/Filter"),
57 ("sstc", "Sstc", "Supervisor Timer"),
58];
59
60pub fn strip_rv_prefix(base: &str) -> &str {
62 base.strip_prefix("rv64")
63 .or_else(|| base.strip_prefix("rv32"))
64 .unwrap_or(base)
65}
66
67pub fn parse_extensions_compact(isa: &str) -> String {
69 let isa = isa.to_lowercase();
70 let mut exts = Vec::new();
71
72 let base = isa.split('_').next().unwrap_or(&isa);
74 let ext_part = strip_rv_prefix(base);
75
76 let has_g = ext_part.contains('g');
78
79 let standard = [
82 ('i', "I", false), ('e', "E", false), ('m', "M", true),
85 ('a', "A", true),
86 ('f', "F", true),
87 ('d', "D", true),
88 ('q', "Q", false),
89 ('c', "C", false),
90 ('b', "B", false),
91 ('v', "V", false),
92 ('h', "H", false),
93 ];
94
95 for (ch, name, implied_by_g) in standard {
96 if ext_part.contains(ch) || (has_g && implied_by_g) {
97 exts.push(name);
98 }
99 }
100
101 if has_g && !exts.contains(&"I") && !exts.contains(&"E") {
103 exts.insert(0, "I");
104 }
105
106 exts.join(" ")
107}
108
109pub fn parse_z_extensions(isa: &str) -> String {
111 let isa = isa.to_lowercase();
112 let mut z_exts = Vec::new();
113
114 let base = isa.split('_').next().unwrap_or(&isa);
116 let ext_part = strip_rv_prefix(base);
117 let has_g = ext_part.contains('g');
118
119 if has_g {
121 z_exts.push("zicsr".to_string());
122 z_exts.push("zifencei".to_string());
123 }
124
125 for part in isa.split('_') {
127 if (part.starts_with('z') || part.starts_with('s')) && !z_exts.contains(&part.to_string()) {
128 z_exts.push(part.to_string());
129 }
130 }
131
132 z_exts.join(" ")
133}
134
135pub fn parse_extensions_explained(isa: &str) -> Vec<(String, String)> {
137 let isa = isa.to_lowercase();
138 let base = isa.split('_').next().unwrap_or(&isa);
139 let ext_part = strip_rv_prefix(base);
140 let mut exts = Vec::new();
141
142 for (ch, name, desc) in STANDARD_EXTENSIONS {
143 if ext_part.contains(*ch) {
144 exts.push((name.to_string(), desc.to_string()));
145 }
146 }
147
148 exts
149}
150
151pub fn parse_z_extensions_explained(isa: &str) -> Vec<(String, String)> {
153 let isa = isa.to_lowercase();
154 let mut z_exts = Vec::new();
155
156 for (pattern, name, desc) in Z_EXTENSIONS {
157 if isa.contains(pattern) {
158 z_exts.push((name.to_string(), desc.to_string()));
159 }
160 }
161
162 z_exts
163}
164
165pub fn parse_vector_from_isa(isa: &str) -> Option<String> {
168 let isa = isa.to_lowercase();
169 let base = isa.split('_').next().unwrap_or(&isa);
170 let ext_part = strip_rv_prefix(base);
171
172 if !ext_part.contains('v') && !isa.contains("zve") {
174 return None;
175 }
176
177 let mut details = vec!["Enabled".to_string()];
178
179 if isa.contains("zvl1024b") {
182 details.push("VLEN>=1024".to_string());
183 } else if isa.contains("zvl512b") {
184 details.push("VLEN>=512".to_string());
185 } else if isa.contains("zvl256b") {
186 details.push("VLEN>=256".to_string());
187 } else if isa.contains("zvl128b") {
188 details.push("VLEN>=128".to_string());
189 } else if isa.contains("zvl64b") {
190 details.push("VLEN>=64".to_string());
191 } else if isa.contains("zvl32b") {
192 details.push("VLEN>=32".to_string());
193 }
194 Some(details.join(", "))
197}