1use super::{check_single_wordlength, no_of_digits, TranslationPreference, ValueKind};
2use crate::wave_container::{ScopeId, VarId, VariableMeta};
3
4use eyre::Result;
5use instruction_decoder::Decoder;
6use surfer_translation_types::{check_vector_variable, BasicTranslator, VariableValue};
7
8pub struct InstructionTranslator {
9 pub name: String,
10 pub decoder: Decoder,
11 pub num_bits: u64,
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: u64, value: &VariableValue) -> (String, ValueKind) {
20 let u64_value = match value {
21 VariableValue::BigUint(v) => v.to_u64_digits().last().cloned(),
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 = no_of_digits(num_bits, 4) + 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 as u32)
47 }
48}
49
50pub fn new_rv32_translator() -> InstructionTranslator {
51 InstructionTranslator {
52 name: "RV32".into(),
53 decoder: Decoder::new(&[
54 include_str!("../../../instruction-decoder/toml/RV32I.toml").to_string(),
55 include_str!("../../../instruction-decoder/toml/RV32M.toml").to_string(),
56 include_str!("../../../instruction-decoder/toml/RV32A.toml").to_string(),
57 include_str!("../../../instruction-decoder/toml/RV32F.toml").to_string(),
58 include_str!("../../../instruction-decoder/toml/RV32_Zbb.toml").to_string(),
59 include_str!("../../../instruction-decoder/toml/RV32_Zbkb.toml").to_string(),
60 include_str!("../../../instruction-decoder/toml/RV32_Zbs.toml").to_string(),
61 include_str!("../../../instruction-decoder/toml/RV32_Zknd.toml").to_string(),
62 include_str!("../../../instruction-decoder/toml/RV32_Zkne.toml").to_string(),
63 include_str!("../../../instruction-decoder/toml/RV32_Zfa.toml").to_string(),
64 include_str!("../../../instruction-decoder/toml/RV32_Zicsr.toml").to_string(),
65 include_str!("../../../instruction-decoder/toml/RV32C-lower.toml").to_string(),
66 include_str!("../../../instruction-decoder/toml/RV32_Zcb-lower.toml").to_string(),
67 include_str!("../../../instruction-decoder/toml/RV32_Zcf-lower.toml").to_string(),
68 include_str!("../../../instruction-decoder/toml/RV32_Zacas.toml").to_string(),
69 include_str!("../../../instruction-decoder/toml/RV_Zcd-lower.toml").to_string(),
70 include_str!("../../../instruction-decoder/toml/RV_Zfh.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 ])
86 .expect("Can't build RV32 decoder"),
87 num_bits: 32,
88 }
89}
90
91pub fn new_rv64_translator() -> InstructionTranslator {
92 InstructionTranslator {
93 name: "RV64".into(),
94 decoder: Decoder::new(&[
95 include_str!("../../../instruction-decoder/toml/RV64I.toml").to_string(),
96 include_str!("../../../instruction-decoder/toml/RV64M.toml").to_string(),
97 include_str!("../../../instruction-decoder/toml/RV64A.toml").to_string(),
98 include_str!("../../../instruction-decoder/toml/RV64D.toml").to_string(),
99 include_str!("../../../instruction-decoder/toml/RV64_Zbb.toml").to_string(),
100 include_str!("../../../instruction-decoder/toml/RV64_Zbkb.toml").to_string(),
101 include_str!("../../../instruction-decoder/toml/RV64_Zbs.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_Zfh.toml").to_string(),
122 include_str!("../../../instruction-decoder/toml/RV_Zba.toml").to_string(),
123 include_str!("../../../instruction-decoder/toml/RV_Zbc.toml").to_string(),
124 include_str!("../../../instruction-decoder/toml/RV_Zbkc.toml").to_string(),
125 include_str!("../../../instruction-decoder/toml/RV_Zbkx.toml").to_string(),
126 include_str!("../../../instruction-decoder/toml/RV_Zfh.toml").to_string(),
127 include_str!("../../../instruction-decoder/toml/RV_Zknh.toml").to_string(),
128 include_str!("../../../instruction-decoder/toml/RV_Zksed.toml").to_string(),
129 include_str!("../../../instruction-decoder/toml/RV_Zksh.toml").to_string(),
130 include_str!("../../../instruction-decoder/toml/RV_Zawrs.toml").to_string(),
131 include_str!("../../../instruction-decoder/toml/RV_Zicond.toml").to_string(),
132 include_str!("../../../instruction-decoder/toml/RV_Zifencei.toml").to_string(),
133 include_str!("../../../instruction-decoder/toml/RV_Zicbo.toml").to_string(),
134 include_str!("../../../instruction-decoder/toml/RV_Zimop.toml").to_string(),
135 include_str!("../../../instruction-decoder/toml/RV_Zihintntl.toml").to_string(),
136 ])
137 .expect("Can't build RV64 decoder"),
138 num_bits: 32,
139 }
140}
141
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
153pub fn new_la64_translator() -> InstructionTranslator {
154 InstructionTranslator {
155 name: "LA64".into(),
156 decoder: Decoder::new(&[
157 include_str!("../../../instruction-decoder/toml/la64.toml").to_string()
158 ])
159 .expect("Can't build LA64 decoder"),
160 num_bits: 32,
161 }
162}
163
164#[cfg(test)]
165mod test {
166
167 use super::*;
168
169 #[test]
170 fn riscv_from_bigunit() {
171 let rv32_translator = new_rv32_translator();
172 let rv64_translator = new_rv64_translator();
173 assert_eq!(
174 rv32_translator
175 .basic_translate(32, &VariableValue::BigUint(1u32.into()))
176 .0,
177 "c.nop"
178 );
179 assert_eq!(
180 rv32_translator
181 .basic_translate(32, &VariableValue::BigUint(0b1000000010011111u32.into()))
182 .0,
183 "UNKNOWN INSN (0x0000809f)"
184 );
185 assert_eq!(
186 rv32_translator
187 .basic_translate(
188 32,
189 &VariableValue::BigUint(0b1000_0001_0011_0101_0000_0101_1001_0011_u32.into())
190 )
191 .0,
192 "addi a1, a0, -2029"
193 );
194 assert_eq!(
195 rv64_translator
196 .basic_translate(32, &VariableValue::BigUint(1u32.into()))
197 .0,
198 "c.nop"
199 );
200 assert_eq!(
201 rv64_translator
202 .basic_translate(32, &VariableValue::BigUint(0b1000000010011111u32.into()))
203 .0,
204 "UNKNOWN INSN (0x0000809f)"
205 );
206 assert_eq!(
207 rv64_translator
208 .basic_translate(
209 32,
210 &VariableValue::BigUint(0b1000_0001_0011_0101_0000_0101_1001_0011_u32.into())
211 )
212 .0,
213 "addi a1, a0, -2029"
214 );
215 }
216 #[test]
217 fn riscv_from_string() {
218 let rv32_translator = new_rv32_translator();
219 assert_eq!(
220 rv32_translator
221 .basic_translate(32, &VariableValue::String("1".to_owned()))
222 .0,
223 "c.nop"
224 );
225 assert_eq!(
226 rv32_translator
227 .basic_translate(
228 32,
229 &VariableValue::String("01001000100010001000100011111111".to_owned())
230 )
231 .0,
232 "UNKNOWN INSN (0x488888ff)"
233 );
234 assert_eq!(
235 rv32_translator
236 .basic_translate(
237 32,
238 &VariableValue::String("01xzz-hlw0010001000100010001000".to_owned())
239 )
240 .0,
241 "UNDEF"
242 );
243 assert_eq!(
244 rv32_translator
245 .basic_translate(
246 32,
247 &VariableValue::String("010zz-hlw0010001000100010001000".to_owned())
248 )
249 .0,
250 "HIGHIMP"
251 );
252 assert_eq!(
253 rv32_translator
254 .basic_translate(
255 32,
256 &VariableValue::String("01011-hlw0010001000100010001000".to_owned())
257 )
258 .0,
259 "DON'T CARE"
260 );
261 }
262
263 #[test]
264 fn mips_from_bigunit() {
265 let mips_translator = new_mips_translator();
266 assert_eq!(
267 mips_translator
268 .basic_translate(32, &VariableValue::BigUint(0x3a873u32.into()))
269 .0,
270 "UNKNOWN INSN (0x0003a873)"
271 );
272 assert_eq!(
273 mips_translator
274 .basic_translate(32, &VariableValue::BigUint(0x24210000u32.into()))
275 .0,
276 "addiu $at, $at, 0"
277 );
278 }
279
280 #[test]
281 fn mips_from_string() {
282 let mips_translator = new_mips_translator();
283 assert_eq!(
284 mips_translator
285 .basic_translate(
286 32,
287 &VariableValue::String("10101111110000010000000000000000".to_owned())
288 )
289 .0,
290 "sw $at, 0($fp)"
291 );
292 assert_eq!(
293 mips_translator
294 .basic_translate(
295 32,
296 &VariableValue::String("01xzz-hlw0010001000100010001000".to_owned())
297 )
298 .0,
299 "UNDEF"
300 );
301 assert_eq!(
302 mips_translator
303 .basic_translate(
304 32,
305 &VariableValue::String("010zz-hlw0010001000100010001000".to_owned())
306 )
307 .0,
308 "HIGHIMP"
309 );
310 assert_eq!(
311 mips_translator
312 .basic_translate(
313 32,
314 &VariableValue::String("01011-hlw0010001000100010001000".to_owned())
315 )
316 .0,
317 "DON'T CARE"
318 );
319 }
320
321 #[test]
322 fn la64_from_bigunit() {
323 let la64_translator = new_la64_translator();
324 assert_eq!(
325 la64_translator
326 .basic_translate(32, &VariableValue::BigUint(0xffffffffu32.into()))
327 .0,
328 "UNKNOWN INSN (0xffffffff)"
329 );
330 assert_eq!(
331 la64_translator
332 .basic_translate(32, &VariableValue::BigUint(0x1a000004u32.into()))
333 .0,
334 "pcalau12i $a0, 0"
335 );
336 }
337
338 #[test]
339 fn la64_from_string() {
340 let la64_translator = new_la64_translator();
341 assert_eq!(
342 la64_translator
343 .basic_translate(
344 32,
345 &VariableValue::String("00101001101111111011001011001100".to_owned())
346 )
347 .0,
348 "st.w $t0, $fp, -20"
349 );
350 assert_eq!(
351 la64_translator
352 .basic_translate(
353 32,
354 &VariableValue::String("01xzz-hlw0010001000100010001000".to_owned())
355 )
356 .0,
357 "UNDEF"
358 );
359 assert_eq!(
360 la64_translator
361 .basic_translate(
362 32,
363 &VariableValue::String("010zz-hlw0010001000100010001000".to_owned())
364 )
365 .0,
366 "HIGHIMP"
367 );
368 assert_eq!(
369 la64_translator
370 .basic_translate(
371 32,
372 &VariableValue::String("01011-hlw0010001000100010001000".to_owned())
373 )
374 .0,
375 "DON'T CARE"
376 );
377 }
378}