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}