1use super::{TranslationPreference, ValueKind, check_single_wordlength};
2use crate::wave_container::{ScopeId, VarId, VariableMeta};
3
4use eyre::Result;
5use instruction_decoder::Decoder;
6use surfer_translation_types::{BasicTranslator, VariableValue, check_vector_variable};
7
8pub struct InstructionTranslator {
9 pub name: String,
10 pub decoder: Decoder,
11 pub num_bits: u32,
12}
13
14impl BasicTranslator<VarId, ScopeId> for InstructionTranslator {
15 fn name(&self) -> String {
16 self.name.clone()
17 }
18
19 fn basic_translate(&self, num_bits: u32, value: &VariableValue) -> (String, ValueKind) {
20 let u64_value = match value {
21 VariableValue::BigUint(v) => v.to_u64_digits().last().copied(),
22 VariableValue::String(s) => match check_vector_variable(s) {
23 Some(v) => return v,
24 None => u64::from_str_radix(s, 2).ok(),
25 },
26 }
27 .unwrap_or(0);
28
29 match self
30 .decoder
31 .decode_from_i64(u64_value as i64, num_bits as usize)
32 {
33 Ok(iform) => (iform, ValueKind::Normal),
34 _ => (
35 format!(
36 "UNKNOWN INSN ({:#0width$x})",
37 u64_value,
38 width = num_bits.div_ceil(4) as usize + 2
39 ),
40 ValueKind::Warn,
41 ),
42 }
43 }
44
45 fn translates(&self, variable: &VariableMeta) -> Result<TranslationPreference> {
46 check_single_wordlength(variable.num_bits, self.num_bits)
47 }
48}
49
50#[must_use]
51pub fn new_rv32_translator() -> InstructionTranslator {
52 InstructionTranslator {
53 name: "RV32".into(),
54 decoder: Decoder::new(&[
55 include_str!("../../../instruction-decoder/toml/RV32I.toml").to_string(),
56 include_str!("../../../instruction-decoder/toml/RV32M.toml").to_string(),
57 include_str!("../../../instruction-decoder/toml/RV32A.toml").to_string(),
58 include_str!("../../../instruction-decoder/toml/RV32F.toml").to_string(),
59 include_str!("../../../instruction-decoder/toml/RV32_Zbb.toml").to_string(),
60 include_str!("../../../instruction-decoder/toml/RV32_Zbkb.toml").to_string(),
61 include_str!("../../../instruction-decoder/toml/RV32_Zbs.toml").to_string(),
62 include_str!("../../../instruction-decoder/toml/RV32_Zknd.toml").to_string(),
63 include_str!("../../../instruction-decoder/toml/RV32_Zkne.toml").to_string(),
64 include_str!("../../../instruction-decoder/toml/RV32_Zfa.toml").to_string(),
65 include_str!("../../../instruction-decoder/toml/RV32_Zicsr.toml").to_string(),
66 include_str!("../../../instruction-decoder/toml/RV32C-lower.toml").to_string(),
67 include_str!("../../../instruction-decoder/toml/RV32_Zcb-lower.toml").to_string(),
68 include_str!("../../../instruction-decoder/toml/RV32_Zcf-lower.toml").to_string(),
69 include_str!("../../../instruction-decoder/toml/RV32_Zacas.toml").to_string(),
70 include_str!("../../../instruction-decoder/toml/RV_Zcd-lower.toml").to_string(),
71 include_str!("../../../instruction-decoder/toml/RV_Zba.toml").to_string(),
72 include_str!("../../../instruction-decoder/toml/RV_Zbc.toml").to_string(),
73 include_str!("../../../instruction-decoder/toml/RV_Zbkc.toml").to_string(),
74 include_str!("../../../instruction-decoder/toml/RV_Zbkx.toml").to_string(),
75 include_str!("../../../instruction-decoder/toml/RV_Zfh.toml").to_string(),
76 include_str!("../../../instruction-decoder/toml/RV_Zknh.toml").to_string(),
77 include_str!("../../../instruction-decoder/toml/RV_Zksed.toml").to_string(),
78 include_str!("../../../instruction-decoder/toml/RV_Zksh.toml").to_string(),
79 include_str!("../../../instruction-decoder/toml/RV_Zawrs.toml").to_string(),
80 include_str!("../../../instruction-decoder/toml/RV_Zicond.toml").to_string(),
81 include_str!("../../../instruction-decoder/toml/RV_Zifencei.toml").to_string(),
82 include_str!("../../../instruction-decoder/toml/RV_Zicbo.toml").to_string(),
83 include_str!("../../../instruction-decoder/toml/RV_Zimop.toml").to_string(),
84 include_str!("../../../instruction-decoder/toml/RV_Zihintntl.toml").to_string(),
85 include_str!("../../../instruction-decoder/toml/RVV.toml").to_string(),
86 ])
87 .expect("Can't build RV32 decoder"),
88 num_bits: 32,
89 }
90}
91
92#[must_use]
93pub fn new_rv64_translator() -> InstructionTranslator {
94 InstructionTranslator {
95 name: "RV64".into(),
96 decoder: Decoder::new(&[
97 include_str!("../../../instruction-decoder/toml/RV64I.toml").to_string(),
98 include_str!("../../../instruction-decoder/toml/RV64M.toml").to_string(),
99 include_str!("../../../instruction-decoder/toml/RV64A.toml").to_string(),
100 include_str!("../../../instruction-decoder/toml/RV64D.toml").to_string(),
101 include_str!("../../../instruction-decoder/toml/RV64_Zbb.toml").to_string(),
102 include_str!("../../../instruction-decoder/toml/RV64_Zbkb.toml").to_string(),
103 include_str!("../../../instruction-decoder/toml/RV64_Zbs.toml").to_string(),
104 include_str!("../../../instruction-decoder/toml/RV64_Zknd.toml").to_string(),
105 include_str!("../../../instruction-decoder/toml/RV64_Zkne.toml").to_string(),
106 include_str!("../../../instruction-decoder/toml/RV64_Zacas.toml").to_string(),
107 include_str!("../../../instruction-decoder/toml/RV64_Zfa.toml").to_string(),
108 include_str!("../../../instruction-decoder/toml/RV64C-lower.toml").to_string(),
109 include_str!("../../../instruction-decoder/toml/RV64_Zcb-lower.toml").to_string(),
110 include_str!("../../../instruction-decoder/toml/RV64_Zcd-lower.toml").to_string(),
111 include_str!("../../../instruction-decoder/toml/RVV.toml").to_string(),
112 include_str!("../../../instruction-decoder/toml/RV_Zvbb.toml").to_string(),
113 include_str!("../../../instruction-decoder/toml/RV_Zvbc.toml").to_string(),
114 include_str!("../../../instruction-decoder/toml/RV_Zvkg.toml").to_string(),
115 include_str!("../../../instruction-decoder/toml/RV_Zvkned.toml").to_string(),
116 include_str!("../../../instruction-decoder/toml/RV_Zvknha.toml").to_string(),
117 include_str!("../../../instruction-decoder/toml/RV_Zvknhb.toml").to_string(),
118 include_str!("../../../instruction-decoder/toml/RV_Zvksed.toml").to_string(),
119 include_str!("../../../instruction-decoder/toml/RV_Zvksh.toml").to_string(),
120 include_str!("../../../instruction-decoder/toml/RV_Zcd-lower.toml").to_string(),
121 include_str!("../../../instruction-decoder/toml/RV_Zba.toml").to_string(),
122 include_str!("../../../instruction-decoder/toml/RV_Zbc.toml").to_string(),
123 include_str!("../../../instruction-decoder/toml/RV_Zbkc.toml").to_string(),
124 include_str!("../../../instruction-decoder/toml/RV_Zbkx.toml").to_string(),
125 include_str!("../../../instruction-decoder/toml/RV_Zfh.toml").to_string(),
126 include_str!("../../../instruction-decoder/toml/RV_Zknh.toml").to_string(),
127 include_str!("../../../instruction-decoder/toml/RV_Zksed.toml").to_string(),
128 include_str!("../../../instruction-decoder/toml/RV_Zksh.toml").to_string(),
129 include_str!("../../../instruction-decoder/toml/RV_Zawrs.toml").to_string(),
130 include_str!("../../../instruction-decoder/toml/RV_Zicond.toml").to_string(),
131 include_str!("../../../instruction-decoder/toml/RV_Zifencei.toml").to_string(),
132 include_str!("../../../instruction-decoder/toml/RV_Zicbo.toml").to_string(),
133 include_str!("../../../instruction-decoder/toml/RV_Zimop.toml").to_string(),
134 include_str!("../../../instruction-decoder/toml/RV_Zihintntl.toml").to_string(),
135 ])
136 .expect("Can't build RV64 decoder"),
137 num_bits: 32,
138 }
139}
140
141#[must_use]
142pub fn new_mips_translator() -> InstructionTranslator {
143 InstructionTranslator {
144 name: "MIPS".into(),
145 decoder: Decoder::new(&[
146 include_str!("../../../instruction-decoder/toml/mips.toml").to_string()
147 ])
148 .expect("Can't build mips decoder"),
149 num_bits: 32,
150 }
151}
152
153#[must_use]
154pub fn new_la64_translator() -> InstructionTranslator {
155 InstructionTranslator {
156 name: "LA64".into(),
157 decoder: Decoder::new(&[
158 include_str!("../../../instruction-decoder/toml/la64.toml").to_string()
159 ])
160 .expect("Can't build LA64 decoder"),
161 num_bits: 32,
162 }
163}
164
165#[cfg(test)]
166mod test {
167
168 use super::*;
169
170 #[test]
171 fn riscv_from_bigunit() {
172 let rv32_translator = new_rv32_translator();
173 let rv64_translator = new_rv64_translator();
174 assert_eq!(
175 rv32_translator
176 .basic_translate(32, &VariableValue::BigUint(1u32.into()))
177 .0,
178 "c.nop"
179 );
180 assert_eq!(
181 rv32_translator
182 .basic_translate(32, &VariableValue::BigUint(0b1000000010011111u32.into()))
183 .0,
184 "UNKNOWN INSN (0x0000809f)"
185 );
186 assert_eq!(
187 rv32_translator
188 .basic_translate(
189 32,
190 &VariableValue::BigUint(0b1000_0001_0011_0101_0000_0101_1001_0011_u32.into())
191 )
192 .0,
193 "addi a1, a0, -2029"
194 );
195 assert_eq!(
196 rv64_translator
197 .basic_translate(32, &VariableValue::BigUint(1u32.into()))
198 .0,
199 "c.nop"
200 );
201 assert_eq!(
202 rv64_translator
203 .basic_translate(32, &VariableValue::BigUint(0b1000000010011111u32.into()))
204 .0,
205 "UNKNOWN INSN (0x0000809f)"
206 );
207 assert_eq!(
208 rv64_translator
209 .basic_translate(
210 32,
211 &VariableValue::BigUint(0b1000_0001_0011_0101_0000_0101_1001_0011_u32.into())
212 )
213 .0,
214 "addi a1, a0, -2029"
215 );
216 }
217 #[test]
218 fn riscv_from_string() {
219 let rv32_translator = new_rv32_translator();
220 assert_eq!(
221 rv32_translator
222 .basic_translate(32, &VariableValue::String("1".to_owned()))
223 .0,
224 "c.nop"
225 );
226 assert_eq!(
227 rv32_translator
228 .basic_translate(
229 32,
230 &VariableValue::String("01001000100010001000100011111111".to_owned())
231 )
232 .0,
233 "UNKNOWN INSN (0x488888ff)"
234 );
235 assert_eq!(
236 rv32_translator
237 .basic_translate(
238 32,
239 &VariableValue::String("01xzz-hlw0010001000100010001000".to_owned())
240 )
241 .0,
242 "UNDEF"
243 );
244 assert_eq!(
245 rv32_translator
246 .basic_translate(
247 32,
248 &VariableValue::String("010zz-hlw0010001000100010001000".to_owned())
249 )
250 .0,
251 "HIGHIMP"
252 );
253 assert_eq!(
254 rv32_translator
255 .basic_translate(
256 32,
257 &VariableValue::String("01011-hlw0010001000100010001000".to_owned())
258 )
259 .0,
260 "DON'T CARE"
261 );
262 }
263
264 #[test]
265 fn mips_from_bigunit() {
266 let mips_translator = new_mips_translator();
267 assert_eq!(
268 mips_translator
269 .basic_translate(32, &VariableValue::BigUint(0x3a873u32.into()))
270 .0,
271 "UNKNOWN INSN (0x0003a873)"
272 );
273 assert_eq!(
274 mips_translator
275 .basic_translate(32, &VariableValue::BigUint(0x24210000u32.into()))
276 .0,
277 "addiu $at, $at, 0"
278 );
279 }
280
281 #[test]
282 fn mips_from_string() {
283 let mips_translator = new_mips_translator();
284 assert_eq!(
285 mips_translator
286 .basic_translate(
287 32,
288 &VariableValue::String("10101111110000010000000000000000".to_owned())
289 )
290 .0,
291 "sw $at, 0($fp)"
292 );
293 assert_eq!(
294 mips_translator
295 .basic_translate(
296 32,
297 &VariableValue::String("01xzz-hlw0010001000100010001000".to_owned())
298 )
299 .0,
300 "UNDEF"
301 );
302 assert_eq!(
303 mips_translator
304 .basic_translate(
305 32,
306 &VariableValue::String("010zz-hlw0010001000100010001000".to_owned())
307 )
308 .0,
309 "HIGHIMP"
310 );
311 assert_eq!(
312 mips_translator
313 .basic_translate(
314 32,
315 &VariableValue::String("01011-hlw0010001000100010001000".to_owned())
316 )
317 .0,
318 "DON'T CARE"
319 );
320 }
321
322 #[test]
323 fn la64_from_bigunit() {
324 let la64_translator = new_la64_translator();
325 assert_eq!(
326 la64_translator
327 .basic_translate(32, &VariableValue::BigUint(0xffffffffu32.into()))
328 .0,
329 "UNKNOWN INSN (0xffffffff)"
330 );
331 assert_eq!(
332 la64_translator
333 .basic_translate(32, &VariableValue::BigUint(0x1a000004u32.into()))
334 .0,
335 "pcalau12i $a0, 0"
336 );
337 }
338
339 #[test]
340 fn la64_from_string() {
341 let la64_translator = new_la64_translator();
342 assert_eq!(
343 la64_translator
344 .basic_translate(
345 32,
346 &VariableValue::String("00101001101111111011001011001100".to_owned())
347 )
348 .0,
349 "st.w $t0, $fp, -20"
350 );
351 assert_eq!(
352 la64_translator
353 .basic_translate(
354 32,
355 &VariableValue::String("01xzz-hlw0010001000100010001000".to_owned())
356 )
357 .0,
358 "UNDEF"
359 );
360 assert_eq!(
361 la64_translator
362 .basic_translate(
363 32,
364 &VariableValue::String("010zz-hlw0010001000100010001000".to_owned())
365 )
366 .0,
367 "HIGHIMP"
368 );
369 assert_eq!(
370 la64_translator
371 .basic_translate(
372 32,
373 &VariableValue::String("01011-hlw0010001000100010001000".to_owned())
374 )
375 .0,
376 "DON'T CARE"
377 );
378 }
379}