armagnac/instructions/
mod.rs

1//! ARM instructions implementation module.
2//!
3//! Each implemented instruction has its own submodule, holding a struct for each variant
4//! (immediate, register, etc.) of the instruction. For example, the AND instruction is implemented
5//! in the [and] module by the [and::AndImm] for the Immediate variant and [and::AndReg] for the
6//! Register variant.
7
8use crate::{
9    arm::{ArmProcessor, RunError},
10    condition::Condition,
11    decoder::DecodeError,
12    it_state::ItState,
13    registers::RegisterIndex,
14};
15
16pub mod adc;
17pub mod add;
18pub mod adr;
19pub mod and;
20pub mod asr;
21pub mod b;
22pub mod bfc;
23pub mod bfi;
24pub mod bic;
25pub mod bl;
26pub mod blx;
27pub mod bx;
28pub mod cbnz;
29pub mod clz;
30pub mod cmn;
31pub mod cmp;
32pub mod cps;
33pub mod dmb;
34pub mod dsb;
35pub mod eor;
36pub mod isb;
37pub mod it;
38pub mod ldm;
39pub mod ldmdb;
40pub mod ldr;
41pub mod ldrb;
42pub mod ldrd;
43pub mod ldrh;
44pub mod ldrsb;
45pub mod ldrsh;
46pub mod lsl;
47pub mod lsr;
48pub mod mla;
49pub mod mls;
50pub mod mov;
51pub mod movt;
52pub mod mrs;
53pub mod msr;
54pub mod mul;
55pub mod mvn;
56pub mod nop;
57pub mod orn;
58pub mod orr;
59pub mod pop;
60pub mod push;
61pub mod qadd;
62pub mod qadd16;
63pub mod qadd8;
64pub mod qdadd;
65pub mod qdsub;
66pub mod qsub;
67pub mod qsub16;
68pub mod qsub8;
69pub mod rbit;
70pub mod rev;
71pub mod rev16;
72pub mod ror;
73pub mod rrx;
74pub mod rsb;
75pub mod sbc;
76pub mod sbfx;
77pub mod sdiv;
78pub mod sev;
79pub mod stm;
80pub mod stmdb;
81pub mod str;
82pub mod strb;
83pub mod strh;
84pub mod sub;
85pub mod svc;
86pub mod sxtb;
87pub mod sxth;
88pub mod tbb;
89pub mod teq;
90pub mod tst;
91pub mod ubfx;
92pub mod udiv;
93pub mod umlal;
94pub mod umull;
95pub mod uxtb;
96pub mod uxth;
97
98/// All instructions must implement this trait in order to be integrated into the emulator.
99pub trait Instruction {
100    /// Returns a list of string patterns the instruction can match.
101    ///
102    /// Patterns must define each bit of the instruction with following possible symbols:
103    /// - "0" when a bit must be zero,
104    /// - "1" when a bit must be one,
105    /// - "x" for bits part of instruction arguments (registers indexes, immediate values, etc.),
106    /// - "(0)" for bits part of instruction arguments, but expected to be zero,
107    /// - "(1)" for bits part of instruction arguments, but expected to be one.
108    ///
109    /// In the returned array, element 0 is the pattern for T1 encoding, element 1 for T2 encoding,
110    /// etc.
111    ///
112    /// Patterns format matches the patterns indicated in the ARM Architecture Reference Manual,
113    /// making easy to define them with little room for mistakes.
114    ///
115    /// Patterns can have 16 or 32 symbols. If not, the instruction decoder is expected to panic.
116    ///
117    /// For instance, the pattern "0001110xxxxxxxxx" matches the ADD instruction T1 encoding.
118    fn patterns() -> &'static [&'static str]
119    where
120        Self: Sized;
121
122    /// Tries to decode a 16-bit or 32-bit instruction.
123    ///
124    /// `tn` corresponds to the matched encoding (1 for T1, 2 for T2, etc.) and `ins` is the
125    /// instruction value. The current IT state is also passed as parameter, as an instruction can
126    /// have a different behavior whether it is executed inside an IT block or not.
127    ///
128    /// If an instruction matches a pattern but the arguments values lead to another instruction
129    /// instead, [DecodeError::Other] is to be returned so the instruction decoder will try to find
130    /// another matching instruction. Depending on instruction arguments
131    /// [DecodeError::Unpredictable] or [DecodeError::Undefined] may be returned as well. Those
132    /// errors always matches the precise description of the ARM Technical Reference Manual.
133    ///
134    /// [other], [unpredictable] and [undefined] methods can be used as shorthands for testing
135    /// conditions and returning corresponding errors, as in the following example:
136    ///
137    /// ```
138    /// # use armagnac::instructions::DecodeHelper;
139    /// # use armagnac::instructions::unpredictable;
140    /// # use armagnac::decoder::DecodeError;
141    /// # let ins = 0u32;
142    /// let rd = ins.reg4(0);
143    /// unpredictable(rd.is_sp_or_pc())?;
144    /// # Ok::<(), DecodeError>(())
145    /// ```
146    fn try_decode(tn: usize, ins: u32, state: ItState) -> Result<Self, DecodeError>
147    where
148        Self: Sized;
149
150    /// Returns instruction execution own condition, or [None] if the condition in the IT state is
151    /// to be followed. Only the B instruction in T1 and T3 encodings should implement this, all
152    /// other instructions rely on the blanket implementation which returns [None].
153    fn condition(&self) -> Option<Condition> {
154        None
155    }
156
157    /// Execute the instruction and updates given `proc` processor state.
158    ///
159    /// Returns `Ok(true)` if the instruction has branching effect, `Ok(false)` if not, or
160    /// eventually an execution error such has invalid memory access for instance.
161    fn execute(&self, proc: &mut ArmProcessor) -> Result<bool, RunError>;
162
163    /// Returns name of the instruction to be shown in its mnemonic.
164    ///
165    /// Returned name can be dynamic depending on the instruction effect. In particular, 's' suffix
166    /// may appear when the instruction updates the processor condition flags.
167    fn name(&self) -> String;
168
169    /// Formats and returns arguments strings to be shown in the instruction mnemonic.
170    ///
171    /// Here is a typical example:
172    /// ```
173    /// # use armagnac::registers::RegisterIndex;
174    /// # struct Demo {
175    /// #     rd: RegisterIndex,
176    /// #     rn: RegisterIndex
177    /// # }
178    /// # impl Demo {
179    /// #     fn args(&self) -> String {
180    /// format!("{}, {}", self.rd, self.rn)
181    /// #     }
182    /// # }
183    /// ```
184    ///
185    /// Some formatting helper methods are provided and can be used: see [rdn_args_string],
186    /// [indexing_args] or [crate::arith::Shift::arg_string].
187    fn args(&self, pc: u32) -> String;
188}
189
190/// If condition passes, returns [DecodeError::Unpredictable] error.
191pub fn unpredictable(cond: bool) -> Result<(), DecodeError> {
192    if cond {
193        Err(DecodeError::Unpredictable)
194    } else {
195        Ok(())
196    }
197}
198
199/// If condition passes, returns [DecodeError::Undefined] error.
200pub fn undefined(cond: bool) -> Result<(), DecodeError> {
201    if cond {
202        Err(DecodeError::Undefined)
203    } else {
204        Ok(())
205    }
206}
207
208/// If condition passes, returns [DecodeError::Other] error.
209pub fn other(cond: bool) -> Result<(), DecodeError> {
210    if cond {
211        Err(DecodeError::Other)
212    } else {
213        Ok(())
214    }
215}
216
217/// Possible instruction sizes for ARM Thumb.
218#[derive(Copy, Clone, PartialEq, Debug)]
219pub enum InstructionSize {
220    /// 16-bit instruction.
221    Ins16 = 2,
222    /// 32-bit instruction.
223    Ins32 = 4,
224}
225
226impl InstructionSize {
227    /// Returns thumb instruction size based on first halfword value.
228    /// This is used by the instruction decoder.
229    pub fn from_halfword(halfword: u16) -> Self {
230        match (halfword & 0xf800) >> 11 {
231            0b11101..=0b11111 => InstructionSize::Ins32,
232            _ => InstructionSize::Ins16,
233        }
234    }
235}
236
237/// Trait to facilitate fields and arguments extraction from an instruction encoding.
238pub trait DecodeHelper {
239    /// Extracts a 3-bit register index at `lsb_index` bit position.
240    fn reg3(&self, lsb_index: u8) -> RegisterIndex;
241
242    /// Extracts a 4-bit register index at `lsb_index` bit position.
243    fn reg4(&self, lsb_index: u8) -> RegisterIndex;
244
245    /// Extracts a single bit integer value at `lsb_index` bit position.
246    fn imm1(&self, lsb_index: u8) -> u32;
247
248    /// Extracts a 2-bit integer value at `lsb_index` bit position.
249    fn imm2(&self, lsb_index: u8) -> u32;
250
251    /// Extracts a 3-bit integer value at `lsb_index` bit position.
252    fn imm3(&self, lsb_index: u8) -> u32;
253
254    /// Extracts a 4-bit integer value at `lsb_index` bit position.
255    fn imm4(&self, lsb_index: u8) -> u32;
256
257    /// Extracts a 5-bit integer value at `lsb_index` bit position.
258    fn imm5(&self, lsb_index: u8) -> u32;
259
260    /// Extracts a 7-bit integer value at `lsb_index` bit position.
261    fn imm7(&self, lsb_index: u8) -> u32;
262
263    /// Extracts a 8-bit integer value at `lsb_index` bit position.
264    fn imm8(&self, lsb_index: u8) -> u32;
265
266    /// Extracts a 12-bit integer value at `lsb_index` bit position.
267    fn imm12(&self, lsb_index: u8) -> u32;
268
269    /// Extracts `index`, `add` and `wback` flags respectively from bits 10, 9 and 8.
270    fn puw(&self) -> (bool, bool, bool);
271}
272
273impl DecodeHelper for u32 {
274    fn reg3(&self, lsb_index: u8) -> RegisterIndex {
275        RegisterIndex::new_main((self >> lsb_index) & 0x7)
276    }
277
278    fn reg4(&self, lsb_index: u8) -> RegisterIndex {
279        RegisterIndex::new_main((self >> lsb_index) & 0xf)
280    }
281
282    fn imm1(&self, lsb_index: u8) -> u32 {
283        (self >> lsb_index) & 1
284    }
285
286    fn imm2(&self, lsb_index: u8) -> u32 {
287        (self >> lsb_index) & 3
288    }
289
290    fn imm3(&self, lsb_index: u8) -> u32 {
291        (self >> lsb_index) & 7
292    }
293
294    fn imm4(&self, lsb_index: u8) -> u32 {
295        (self >> lsb_index) & 0xf
296    }
297
298    fn imm5(&self, lsb_index: u8) -> u32 {
299        (self >> lsb_index) & 0x1f
300    }
301
302    fn imm7(&self, lsb_index: u8) -> u32 {
303        (self >> lsb_index) & 0x7f
304    }
305
306    fn imm8(&self, lsb_index: u8) -> u32 {
307        (self >> lsb_index) & 0xff
308    }
309
310    fn imm12(&self, lsb_index: u8) -> u32 {
311        (self >> lsb_index) & 0xfff
312    }
313
314    fn puw(&self) -> (bool, bool, bool) {
315        (
316            self & (1 << 10) != 0,
317            self & (1 << 9) != 0,
318            self & (1 << 8) != 0,
319        )
320    }
321}
322
323/// Returns "{rd}" if rd is equal to rn, else "{rd}, {rn}".
324///
325/// This is a convenient method used for many instruction arguments formatting.
326pub fn rdn_args_string(rd: RegisterIndex, rn: RegisterIndex) -> String {
327    if rd == rn {
328        format!("{rd}")
329    } else {
330        format!("{rd}, {rn}")
331    }
332}
333
334/// Returns instruction indexing argument string.
335///
336/// Depending on the `index`, `add`, `wback` and `imm` parameters, can be one of
337/// - "[Rn]"
338/// - "[Rn, #imm]"
339/// - "[Rn], #imm"
340/// - "[Rn, #imm]!"
341pub fn indexing_args(rn: RegisterIndex, imm: u32, index: bool, add: bool, wback: bool) -> String {
342    let neg = if add { "" } else { "-" };
343    match (index, wback) {
344        (true, false) => {
345            let imm = if imm != 0 {
346                format!(", #{}{}", neg, imm)
347            } else {
348                "".into()
349            };
350            format!("[{}{}]", rn, imm)
351        }
352        (true, true) => format!("[{rn}, #{neg}{imm}]!"),
353        (false, true) => format!("[{rn}], #{neg}{imm}"),
354        (false, false) => panic!(),
355    }
356}
357
358/// Utility trait to call either addition or subtraction between two values depending on a
359/// condition.
360///
361/// This is to be used by many instructions which have a bit indicating if an offset is to be added
362/// to a base value, or subtracted.
363pub trait AddOrSub {
364    /// Returns `self + rhs` if `add` is `true`, `self - rhs` otherwise.
365    fn add_or_sub(&self, rhs: Self, add: bool) -> Self;
366
367    /// Returns `self.wrapping_add(rhs)` if `add` is `true`, `self.wrapping_sub(rhs)` otherwise.
368    fn wrapping_add_or_sub(&self, rhs: Self, add: bool) -> Self;
369}
370
371impl AddOrSub for u32 {
372    fn add_or_sub(&self, rhs: Self, add: bool) -> Self {
373        if add {
374            self + rhs
375        } else {
376            self - rhs
377        }
378    }
379
380    fn wrapping_add_or_sub(&self, rhs: Self, add: bool) -> Self {
381        if add {
382            self.wrapping_add(rhs)
383        } else {
384            self.wrapping_sub(rhs)
385        }
386    }
387}
388
389pub trait Mnemonic {
390    fn mnemonic(&self, pc: u32) -> String;
391}
392
393impl Mnemonic for Box<dyn Instruction> {
394    fn mnemonic(&self, pc: u32) -> String {
395        let args = self.args(pc);
396        if args.len() > 0 {
397            format!("{:<6} {}", self.name(), self.args(pc))
398        } else {
399            self.name()
400        }
401    }
402}
403
404#[cfg(test)]
405mod tests {
406    use crate::{
407        instructions::{indexing_args, rdn_args_string, DecodeHelper, InstructionSize},
408        registers::RegisterIndex,
409    };
410
411    #[test]
412    fn test_decode_helper() {
413        // Test reg3
414        for i in 0..=7 {
415            for j in 0..=29 {
416                assert_eq!((i << j).reg3(j), RegisterIndex::new_main(i));
417            }
418        }
419
420        // Test reg4
421        for i in 0..=15 {
422            for j in 0..=28 {
423                assert_eq!((i << j).reg4(j), RegisterIndex::new_main(i));
424            }
425        }
426
427        // Test imm1
428        for i in 0..=1 {
429            for j in 0..=31 {
430                assert_eq!((i << j).imm1(j), i);
431            }
432        }
433
434        // Test imm2
435        for i in 0..=3 {
436            for j in 0..=30 {
437                assert_eq!((i << j).imm2(j), i);
438            }
439        }
440
441        // Test imm3
442        for i in 0..=7 {
443            for j in 0..=29 {
444                assert_eq!((i << j).imm3(j), i);
445            }
446        }
447
448        // Test imm4
449        for i in 0..=15 {
450            for j in 0..=28 {
451                assert_eq!((i << j).imm4(j), i);
452            }
453        }
454
455        // Test imm5
456        for i in 0..=31 {
457            for j in 0..=27 {
458                assert_eq!((i << j).imm5(j), i);
459            }
460        }
461
462        // Test imm8
463        for i in 0..=255 {
464            for j in 0..=24 {
465                assert_eq!((i << j).imm8(j), i);
466            }
467        }
468
469        // Test imm12
470        for i in 0..=4095 {
471            for j in 0..=20 {
472                assert_eq!((i << j).imm12(j), i);
473            }
474        }
475
476        // Test puw
477        for i in 0..7 {
478            assert_eq!(
479                (i << 8).puw(),
480                (i & 0b100 != 0, i & 0b010 != 0, i & 0b001 != 0)
481            )
482        }
483    }
484
485    #[test]
486    fn test_instruction_size() {
487        for i in 0..u16::MAX {
488            assert_eq!(
489                InstructionSize::from_halfword(i),
490                if i >= 0xe800 {
491                    InstructionSize::Ins32
492                } else {
493                    InstructionSize::Ins16
494                }
495            )
496        }
497    }
498
499    #[test]
500    fn test_rdn_args_string() {
501        assert_eq!(rdn_args_string(RegisterIndex::R0, RegisterIndex::R0), "r0");
502        assert_eq!(
503            rdn_args_string(RegisterIndex::R0, RegisterIndex::R1),
504            "r0, r1"
505        );
506    }
507
508    #[test]
509    fn test_indexing_args() {
510        assert_eq!(
511            indexing_args(RegisterIndex::R1, 0, true, true, false),
512            "[r1]"
513        );
514        assert_eq!(
515            indexing_args(RegisterIndex::R1, 0, true, false, false),
516            "[r1]"
517        );
518        assert_eq!(
519            indexing_args(RegisterIndex::R1, 12, true, true, false),
520            "[r1, #12]"
521        );
522        assert_eq!(
523            indexing_args(RegisterIndex::R1, 12, true, false, false),
524            "[r1, #-12]"
525        );
526
527        assert_eq!(
528            indexing_args(RegisterIndex::R1, 0, true, true, true),
529            "[r1, #0]!"
530        );
531        assert_eq!(
532            indexing_args(RegisterIndex::R1, 0, true, false, true),
533            "[r1, #-0]!"
534        );
535        assert_eq!(
536            indexing_args(RegisterIndex::R1, 12, true, true, true),
537            "[r1, #12]!"
538        );
539        assert_eq!(
540            indexing_args(RegisterIndex::R1, 12, true, false, true),
541            "[r1, #-12]!"
542        );
543
544        assert_eq!(
545            indexing_args(RegisterIndex::R1, 0, false, true, true),
546            "[r1], #0"
547        );
548        assert_eq!(
549            indexing_args(RegisterIndex::R1, 0, false, false, true),
550            "[r1], #-0"
551        );
552        assert_eq!(
553            indexing_args(RegisterIndex::R1, 12, false, true, true),
554            "[r1], #12"
555        );
556        assert_eq!(
557            indexing_args(RegisterIndex::R1, 12, false, false, true),
558            "[r1], #-12"
559        );
560    }
561}