libsurfer/translation/
instruction_translators.rs

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}