libsurfer/translation/
instruction_translators.rs

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}