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