armv6_m_instruction_parser/
lib.rs

1//! Library to parse ARMv6-M thumb instructions.
2//!
3//! Provides a enum with all instructions, register types and a function to parse binary representation into the enum with proper arguments.
4//!
5//! # Example
6//! ```
7//! # use armv6_m_instruction_parser::parse;
8//! # fn main() {
9//! #   let program_memory = [0xb0, 0xb5, 0xaf, 0x02];
10//!     match parse(&program_memory[0..4]) {
11//!         Ok(instruction) => println!("Instruction: {:?}", instruction),
12//!         Err(_) => println!("Not a valid instruction.")
13//!     }
14//! # }
15//! ```
16
17pub mod conditions;
18pub mod instructons;
19pub mod registers;
20
21use conditions::Condition;
22use instructons::*;
23use registers::*;
24use tracing::debug;
25
26/// This function parses a input byte slice into one instruction.
27/// Returns Err(&str) if instruction is invalid.
28pub fn parse(input: &[u8]) -> Result<Instruction, &str> {
29    if input.len() < 2 {
30        return Err("input not long enough for a instruction");
31    }
32    let mut instruction_bytes1: [u8; 2] = [0; 2];
33    instruction_bytes1.copy_from_slice(&input[0..2]);
34    let instruction_bits1 = u16::from_le_bytes(instruction_bytes1);
35
36    match (instruction_bits1 >> 11) & 0x1f {
37        0b11101 | 0b11110 | 0b11111 => {
38            // Check if it is a 32-bit instruction.
39            if input.len() < 4 {
40                return Err("32 bit instruction not long enough");
41            };
42            let mut instruction_bytes2: [u8; 2] = [0; 2];
43            instruction_bytes2.copy_from_slice(&input[2..4]);
44            let instruction_bits2 = u16::from_le_bytes(instruction_bytes2);
45            let instruction_bits: u32 = (instruction_bits1 as u32) << 16 | instruction_bits2 as u32;
46            debug!("instruction bits: {:#034b}", instruction_bits);
47            Ok(Instruction {
48                width: InstructionWidth::Bit32,
49                operation: parse_32bit_operation(instruction_bits)?,
50            })
51        }
52        _ => {
53            debug!("instruction bits: {:#018b}", instruction_bits1);
54            Ok(Instruction {
55                width: InstructionWidth::Bit16,
56                operation: parse_16bit_operation(instruction_bits1)?,
57            })
58        }
59    }
60}
61
62fn parse_32bit_operation(input: u32) -> Result<Operation, &'static str> {
63    let op1 = (input >> 27) & 0x3;
64    let op = (input >> 15) & 0x1;
65
66    match (op1, op) {
67        (0b10, 0b1) => {
68            // brach and misc control
69            parse_branch_misc_ctrl(input)
70        }
71        (_, _) => Err("opcode not matching valid 32 bit instruction"),
72    }
73}
74
75fn parse_branch_misc_ctrl(input: u32) -> Result<Operation, &'static str> {
76    let op1 = (input >> 20) & 0x7f;
77    let op2 = (input >> 12) & 0x7;
78
79    match (op2, op1) {
80        (0b000 | 0b010, 0b0111000..=0b0111001) => {
81            // MSR
82            let rn = (((input >> 16) & 0xf) as u8).try_into().unwrap();
83            let sysm = ((input & 0xff) as u8).try_into()?; // can fail
84            Ok(Operation::MSRReg { n: rn, sysm: sysm })
85        }
86        (0b000 | 0b010, 0b0111011) => {
87            // misc control
88            parse_misc_ctrl(input)
89        }
90        (0b000 | 0b010, 0b0111110..=0b0111111) => {
91            // MRS
92            let rd = (((input >> 8) & 0xf) as u8).try_into().unwrap();
93            let sysm = ((input & 0xff) as u8).try_into()?;
94            Ok(Operation::MRS { d: rd, sysm: sysm })
95        }
96        (0b010, 0b1111111) => {
97            let imm = ((input & 0xf0000) >> 4) | (input & 0xfff);
98            Ok(Operation::UDF { imm: imm })
99        }
100        (0b101 | 0b111, _) => {
101            // BL
102            let s = (input >> 26) & 0x1;
103            let j1 = (input >> 13) & 0x1;
104            let j2 = (input >> 11) & 0x1;
105            let i1 = !(j1 ^ s) & 0x1;
106            let i2 = !(j2 ^ s) & 0x1;
107            let imm10 = (input >> 16) & 0x3ff;
108            let imm11 = input & 0x7ff;
109            let imm = ((s << 24) | (i1 << 23) | (i2 << 22) | (imm10 << 12) | (imm11 << 1))
110                .sign_extend(25);
111
112            Ok(Operation::BL { imm: imm })
113        }
114        _ => Err("opcode not matching valid 32 bit instruction"),
115    }
116}
117
118fn parse_misc_ctrl(input: u32) -> Result<Operation, &'static str> {
119    let op = (input >> 4) & 0xf;
120
121    match op {
122        0b0100 => {
123            let option = input & 0xf;
124            Ok(Operation::DSB {
125                option: option as u8,
126            })
127        }
128        0b0101 => {
129            let option = input & 0xf;
130            Ok(Operation::DMB {
131                option: option as u8,
132            })
133        }
134        0b0110 => {
135            let option = input & 0xf;
136            Ok(Operation::ISB {
137                option: option as u8,
138            })
139        }
140        _ => Err("Not a valid op code"),
141    }
142}
143
144fn parse_16bit_operation(input: u16) -> Result<Operation, &'static str> {
145    let opcode = (input >> 10) & 0x3f;
146    match opcode {
147        0b000000..=0b001111 => {
148            parse_arith_instructions(input) // A5-85
149        }
150        0b010000 => {
151            parse_data_processing_instruction(input) // A5-86
152        }
153        0b010001 => {
154            parse_special_data_branch_exchange_instruction(input) // A5-86
155        }
156        0b010010..=0b010011 => {
157            // A6-141
158            // LDR literal
159            let rt: Register = (((input >> 8) & 0x7) as u8).try_into().unwrap();
160            let imm = ((input & 0xff) << 2) as u32;
161            Ok(Operation::LDRLiteral { t: rt, imm: imm })
162        }
163        0b010100..=0b100111 => {
164            // A5-88
165            parse_load_store_instruction(input)
166        }
167        0b101000..=0b101001 => {
168            // A6-115
169            let rd: Register = (((input >> 8) & 0x7) as u8).try_into().unwrap();
170            let imm = ((input & 0xff) << 2) as u32;
171            Ok(Operation::ADR { d: rd, imm: imm })
172        }
173        0b101010..=0b101011 => {
174            // A6-111
175            let rd: Register = (((input >> 8) & 0x7) as u8).try_into().unwrap();
176            let imm = ((input & 0xff) << 2) as u32;
177            Ok(Operation::ADDImmSP { d: rd, imm: imm })
178        }
179        0b101100..=0b101111 => {
180            parse_misc_16_bit(input) // A5-86
181        }
182        0b110000..=0b110001 => {
183            // A6-175
184            let rn: Register = (((input >> 8) & 0x7) as u8).try_into().unwrap();
185            let reg_list_bits = input & 0xff;
186            let reg_list = register_list_from_bit_array(reg_list_bits);
187            Ok(Operation::STM {
188                n: rn,
189                reg_list: reg_list,
190            })
191        }
192        0b110010..=0b110011 => {
193            // A6-137
194            let rn: Register = (((input >> 8) & 0x7) as u8).try_into().unwrap();
195            let reg_list_bits = input & 0xff;
196            let reg_list = register_list_from_bit_array(reg_list_bits);
197            Ok(Operation::LDM {
198                n: rn,
199                reg_list: reg_list,
200            })
201        }
202        0b110100..=0b110111 => {
203            // A5-90
204            parse_conditional_branch(input)
205        }
206        0b111000..=0b111001 => {
207            // A6-119
208            // Unconditional branch
209            let imm = ((input & 0x7ff) << 1).sign_extend(12);
210            Ok(Operation::B {
211                cond: Condition::None,
212                imm: imm,
213            })
214        }
215        _ => Err("not a valid opcode"),
216    }
217}
218
219fn parse_conditional_branch(input: u16) -> Result<Operation, &'static str> {
220    let opcode = (input >> 8) & 0xf;
221
222    match opcode {
223        0b1110 => {
224            // This is by definition in a undefined instruction should generate
225            // a undefined instruction exception.
226            let imm = (input & 0xff) as u32;
227            Ok(Operation::UDF { imm })
228        },
229        0b1111 => {
230            // SVC
231            let imm = (input & 0xff) as u32;
232            Ok(Operation::SVC { imm: imm })
233        }
234        _ => {
235            // B
236            let imm = ((input & 0xff) << 1).sign_extend(9);
237            let cond: Condition = (((input >> 8) & 0xf) as u8).try_into()?;
238            Ok(Operation::B {
239                cond: cond,
240                imm: imm,
241            })
242        }
243    }
244}
245
246fn parse_load_store_instruction(input: u16) -> Result<Operation, &'static str> {
247    let op_a = (input >> 12) & 0xf;
248    let op_b = (input >> 9) & 0x7;
249
250    match (op_a, op_b) {
251        (0b0101, op_b) => match op_b {
252            0b000 => {
253                // STR reg
254                let rm: Register = (((input >> 6) & 0x7) as u8).try_into().unwrap();
255                let rn: Register = (((input >> 3) & 0x7) as u8).try_into().unwrap();
256                let rt: Register = ((input & 0x7) as u8).try_into().unwrap();
257                Ok(Operation::STRReg {
258                    m: rm,
259                    n: rn,
260                    t: rt,
261                })
262            }
263            0b001 => {
264                // STRH reg
265                let rm: Register = (((input >> 6) & 0x7) as u8).try_into().unwrap();
266                let rn: Register = (((input >> 3) & 0x7) as u8).try_into().unwrap();
267                let rt: Register = ((input & 0x7) as u8).try_into().unwrap();
268                Ok(Operation::STRHReg {
269                    m: rm,
270                    n: rn,
271                    t: rt,
272                })
273            }
274            0b010 => {
275                // STRB reg
276                let rm: Register = (((input >> 6) & 0x7) as u8).try_into().unwrap();
277                let rn: Register = (((input >> 3) & 0x7) as u8).try_into().unwrap();
278                let rt: Register = ((input & 0x7) as u8).try_into().unwrap();
279                Ok(Operation::STRBReg {
280                    m: rm,
281                    n: rn,
282                    t: rt,
283                })
284            }
285            0b011 => {
286                // LDRSB reg
287                let rm: Register = (((input >> 6) & 0x7) as u8).try_into().unwrap();
288                let rn: Register = (((input >> 3) & 0x7) as u8).try_into().unwrap();
289                let rt: Register = ((input & 0x7) as u8).try_into().unwrap();
290                Ok(Operation::LDRSBReg {
291                    m: rm,
292                    n: rn,
293                    t: rt,
294                })
295            }
296            0b100 => {
297                // LDR reg
298                let rm: Register = (((input >> 6) & 0x7) as u8).try_into().unwrap();
299                let rn: Register = (((input >> 3) & 0x7) as u8).try_into().unwrap();
300                let rt: Register = ((input & 0x7) as u8).try_into().unwrap();
301                Ok(Operation::LDRReg {
302                    m: rm,
303                    n: rn,
304                    t: rt,
305                })
306            }
307            0b101 => {
308                // LDRH reg
309                let rm: Register = (((input >> 6) & 0x7) as u8).try_into().unwrap();
310                let rn: Register = (((input >> 3) & 0x7) as u8).try_into().unwrap();
311                let rt: Register = ((input & 0x7) as u8).try_into().unwrap();
312                Ok(Operation::LDRHReg {
313                    m: rm,
314                    n: rn,
315                    t: rt,
316                })
317            }
318            0b110 => {
319                // LDRB reg
320                let rm: Register = (((input >> 6) & 0x7) as u8).try_into().unwrap();
321                let rn: Register = (((input >> 3) & 0x7) as u8).try_into().unwrap();
322                let rt: Register = ((input & 0x7) as u8).try_into().unwrap();
323                Ok(Operation::LDRBReg {
324                    m: rm,
325                    n: rn,
326                    t: rt,
327                })
328            }
329            0b111 => {
330                // LDRSH reg
331                let rm: Register = (((input >> 6) & 0x7) as u8).try_into().unwrap();
332                let rn: Register = (((input >> 3) & 0x7) as u8).try_into().unwrap();
333                let rt: Register = ((input & 0x7) as u8).try_into().unwrap();
334                Ok(Operation::LDRSH {
335                    m: rm,
336                    n: rn,
337                    t: rt,
338                })
339            }
340            _ => Err("Invalid opcode"),
341        },
342        (0b0110, op_b) => match op_b {
343            0b000..=0b011 => {
344                // STR
345                let rn: Register = (((input >> 3) & 0x7) as u8).try_into().unwrap();
346                let rt: Register = ((input & 0x7) as u8).try_into().unwrap();
347                let imm = ((input & 0x7c0) >> 4) as u32;
348                Ok(Operation::STRImm {
349                    imm: imm,
350                    n: rn,
351                    t: rt,
352                })
353            }
354            0b100..=0b111 => {
355                // LDR
356                let rn: Register = (((input >> 3) & 0x7) as u8).try_into().unwrap();
357                let rt: Register = ((input & 0x7) as u8).try_into().unwrap();
358                let imm = ((input & 0x7c0) >> 4) as u32;
359                Ok(Operation::LDRImm {
360                    imm: imm,
361                    n: rn,
362                    t: rt,
363                })
364            }
365            _ => Err("Invalid opcode"),
366        },
367        (0b0111, op_b) => match op_b {
368            0b000..=0b011 => {
369                // STRB
370                let rn: Register = (((input >> 3) & 0x7) as u8).try_into().unwrap();
371                let rt: Register = ((input & 0x7) as u8).try_into().unwrap();
372                let imm = ((input & 0x7c0) >> 6) as u32;
373                Ok(Operation::STRBImm {
374                    imm: imm,
375                    n: rn,
376                    t: rt,
377                })
378            }
379            0b100..=0b111 => {
380                // LDRB
381                let rn: Register = (((input >> 3) & 0x7) as u8).try_into().unwrap();
382                let rt: Register = ((input & 0x7) as u8).try_into().unwrap();
383                let imm = ((input & 0x7c0) >> 6) as u32;
384                Ok(Operation::LDRBImm {
385                    imm: imm,
386                    n: rn,
387                    t: rt,
388                })
389            }
390            _ => Err("Invalid opcode"),
391        },
392        (0b1000, op_b) => match op_b {
393            0b000..=0b011 => {
394                // STRH
395                let rn: Register = (((input >> 3) & 0x7) as u8).try_into().unwrap();
396                let rt: Register = ((input & 0x7) as u8).try_into().unwrap();
397                let imm = ((input & 0x7c0) >> 5) as u32;
398                Ok(Operation::STRHImm {
399                    imm: imm,
400                    n: rn,
401                    t: rt,
402                })
403            }
404            0b100..=0b111 => {
405                // LDRH
406                let rn: Register = (((input >> 3) & 0x7) as u8).try_into().unwrap();
407                let rt: Register = ((input & 0x7) as u8).try_into().unwrap();
408                let imm = ((input & 0x7c0) >> 5) as u32;
409                Ok(Operation::LDRHImm {
410                    imm: imm,
411                    n: rn,
412                    t: rt,
413                })
414            }
415            _ => Err("Invalid opcode"),
416        },
417        (0b1001, op_b) => match op_b {
418            0b000..=0b011 => {
419                // STR T2
420                let rt: Register = (((input >> 8) & 0x7) as u8).try_into().unwrap();
421                let imm = ((input & 0xff) << 2) as u32;
422                Ok(Operation::STRImm {
423                    n: Register::SP,
424                    t: rt,
425                    imm: imm,
426                })
427            }
428            0b100..=0b111 => {
429                // LDR T2
430                let rt: Register = (((input >> 8) & 0x7) as u8).try_into().unwrap();
431                let imm = ((input & 0xff) << 2) as u32;
432                Ok(Operation::LDRImm {
433                    n: Register::SP,
434                    t: rt,
435                    imm: imm,
436                })
437            }
438            _ => Err("Invalid opcode"),
439        },
440        (_, _) => Err("Invalid opcode"),
441    }
442}
443
444fn parse_special_data_branch_exchange_instruction(input: u16) -> Result<Operation, &'static str> {
445    let opcode = (input >> 6) & 0xf;
446    match opcode {
447        0b0000..=0b0011 => {
448            // 01000100xx
449            let rm: Register = (((input >> 3) & 0xf) as u8).try_into().unwrap();
450            let rdn: Register = (((input & 0x7) | ((input >> 4) & 0b1000)) as u8)
451                .try_into()
452                .unwrap();
453            if rdn == Register::SP || rm == Register::SP {
454                if rm == Register::SP {
455                    // T1
456                    Ok(Operation::ADDRegSP { d: rdn, m: rdn })
457                } else {
458                    // T2
459                    Ok(Operation::ADDRegSP {
460                        d: Register::SP,
461                        m: rm,
462                    })
463                }
464            } else {
465                // ADD reg T2
466                Ok(Operation::ADDReg {
467                    m: rm,
468                    n: rdn,
469                    d: rdn,
470                })
471            }
472        }
473        0b0100 => Err("unpredictable"), // Unpredictable
474        0b0101 | 0b0110..=0b0111 => {
475            let rm: Register = (((input >> 3) & 0xf) as u8).try_into().unwrap();
476            let rn: Register = (((input & 0x7) | ((input >> 4) & 0b1000)) as u8)
477                .try_into()
478                .unwrap();
479            Ok(Operation::CMPReg { m: rm, n: rn })
480        }
481        0b1000..=0b1011 => {
482            let rm: Register = (((input >> 3) & 0xf) as u8).try_into().unwrap();
483            let rd: Register = (((input & 0x7) | ((input >> 4) & 0b1000)) as u8)
484                .try_into()
485                .unwrap();
486            Ok(Operation::MOVReg {
487                set_flags: false,
488                m: rm,
489                d: rd,
490            })
491        }
492        0b1100..=0b1101 => {
493            let rm: Register = (((input >> 3) & 0xf) as u8).try_into().unwrap();
494            Ok(Operation::BX { m: rm })
495        }
496        0b1110..=0b1111 => {
497            let rm: Register = (((input >> 3) & 0xf) as u8).try_into().unwrap();
498            Ok(Operation::BLXReg { m: rm })
499        }
500        _ => Err("invalid opcode"),
501    }
502}
503
504fn parse_data_processing_instruction(input: u16) -> Result<Operation, &'static str> {
505    let opcode = (input >> 6) & 0xf;
506    match opcode {
507        0b0000 => {
508            let rm: Register = (((input >> 3) & 0x7) as u8).try_into().unwrap();
509            let rdn: Register = ((input & 0x7) as u8).try_into().unwrap();
510            Ok(Operation::ANDReg { m: rm, dn: rdn })
511        }
512        0b0001 => {
513            let rm: Register = (((input >> 3) & 0x7) as u8).try_into().unwrap();
514            let rdn: Register = ((input & 0x7) as u8).try_into().unwrap();
515            Ok(Operation::EORReg { m: rm, dn: rdn })
516        }
517        0b0010 => {
518            let rm: Register = (((input >> 3) & 0x7) as u8).try_into().unwrap();
519            let rdn: Register = ((input & 0x7) as u8).try_into().unwrap();
520            Ok(Operation::LSLReg { m: rm, dn: rdn })
521        }
522        0b0011 => {
523            let rm: Register = (((input >> 3) & 0x7) as u8).try_into().unwrap();
524            let rdn: Register = ((input & 0x7) as u8).try_into().unwrap();
525            Ok(Operation::LSRReg { m: rm, dn: rdn })
526        }
527        0b0100 => {
528            let rm: Register = (((input >> 3) & 0x7) as u8).try_into().unwrap();
529            let rdn: Register = ((input & 0x7) as u8).try_into().unwrap();
530            Ok(Operation::ASRReg { m: rm, dn: rdn })
531        }
532        0b0101 => {
533            let rm: Register = (((input >> 3) & 0x7) as u8).try_into().unwrap();
534            let rdn: Register = ((input & 0x7) as u8).try_into().unwrap();
535            Ok(Operation::ADCReg {
536                m: rm,
537                n: rdn,
538                d: rdn,
539            })
540        }
541        0b0110 => {
542            let rm: Register = (((input >> 3) & 0x7) as u8).try_into().unwrap();
543            let rdn: Register = ((input & 0x7) as u8).try_into().unwrap();
544            Ok(Operation::SBCReg { m: rm, dn: rdn })
545        }
546        0b0111 => {
547            let rm: Register = (((input >> 3) & 0x7) as u8).try_into().unwrap();
548            let rdn: Register = ((input & 0x7) as u8).try_into().unwrap();
549            Ok(Operation::RORReg { m: rm, dn: rdn })
550        }
551        0b1000 => {
552            let rm: Register = (((input >> 3) & 0x7) as u8).try_into().unwrap();
553            let rn: Register = ((input & 0x7) as u8).try_into().unwrap();
554            Ok(Operation::TSTReg { m: rm, n: rn })
555        }
556        0b1001 => {
557            let rn: Register = (((input >> 3) & 0x7) as u8).try_into().unwrap();
558            let rd: Register = ((input & 0x7) as u8).try_into().unwrap();
559            Ok(Operation::RSBImm { n: rn, d: rd })
560        }
561        0b1010 => {
562            let rm: Register = (((input >> 3) & 0x7) as u8).try_into().unwrap();
563            let rn: Register = ((input & 0x7) as u8).try_into().unwrap();
564            Ok(Operation::CMPReg { m: rm, n: rn })
565        }
566        0b1011 => {
567            let rm: Register = (((input >> 3) & 0x7) as u8).try_into().unwrap();
568            let rn: Register = ((input & 0x7) as u8).try_into().unwrap();
569            Ok(Operation::CMNReg { m: rm, n: rn })
570        }
571        0b1100 => {
572            let rm: Register = (((input >> 3) & 0x7) as u8).try_into().unwrap();
573            let rdn: Register = ((input & 0x7) as u8).try_into().unwrap();
574            Ok(Operation::ORRReg { m: rm, dn: rdn })
575        }
576        0b1101 => {
577            let rn: Register = (((input >> 3) & 0x7) as u8).try_into().unwrap();
578            let rdm: Register = ((input & 0x7) as u8).try_into().unwrap();
579            Ok(Operation::MUL { n: rn, dm: rdm })
580        }
581        0b1110 => {
582            let rm: Register = (((input >> 3) & 0x7) as u8).try_into().unwrap();
583            let rdn: Register = ((input & 0x7) as u8).try_into().unwrap();
584            Ok(Operation::BICReg { m: rm, dn: rdn })
585        }
586        0b1111 => {
587            let rm: Register = (((input >> 3) & 0x7) as u8).try_into().unwrap();
588            let rd: Register = ((input & 0x7) as u8).try_into().unwrap();
589            Ok(Operation::MVNReg { m: rm, d: rd })
590        }
591        _ => Err("invalid opcode"),
592    }
593}
594
595fn parse_arith_instructions(input: u16) -> Result<Operation, &'static str> {
596    // A5-85
597    let opcode = (input >> 9) & 0x1f;
598    match opcode {
599        0b00000..=0b00011 => {
600            //LSL
601            let imm = (input >> 6) & 0x1f;
602            let rm: Register = (((input >> 3) & 0x7) as u8).try_into().unwrap();
603            let rd: Register = ((input & 0x7) as u8).try_into().unwrap();
604            if imm > 0 {
605                Ok(Operation::LSLImm {
606                    imm: imm as u32,
607                    m: rm,
608                    d: rd,
609                })
610            } else {
611                Ok(Operation::MOVReg {
612                    set_flags: true,
613                    m: rm,
614                    d: rd,
615                })
616            }
617        }
618        0b00100..=0b00111 => {
619            //LSR
620            let imm = (input >> 6) & 0x1f;
621            let rm: Register = (((input >> 3) & 0x7) as u8).try_into().unwrap();
622            let rd: Register = ((input & 0x7) as u8).try_into().unwrap();
623            Ok(Operation::LSRImm {
624                imm: imm as u32,
625                m: rm,
626                d: rd,
627            })
628        }
629        0b01000..=0b01011 => {
630            //ASR
631            let imm = (input >> 6) & 0x1f;
632            let rm: Register = (((input >> 3) & 0x7) as u8).try_into().unwrap();
633            let rd: Register = ((input & 0x7) as u8).try_into().unwrap();
634            Ok(Operation::ASRImm {
635                imm: imm as u32,
636                m: rm,
637                d: rd,
638            })
639        }
640        0b01100 => {
641            // ADD reg
642            let rm: Register = (((input >> 6) & 0x7) as u8).try_into().unwrap();
643            let rn: Register = (((input >> 3) & 0x7) as u8).try_into().unwrap();
644            let rd: Register = ((input & 0x7) as u8).try_into().unwrap();
645            Ok(Operation::ADDReg {
646                m: rm,
647                n: rn,
648                d: rd,
649            })
650        }
651        0b01101 => {
652            // SUB reg
653            let rm: Register = (((input >> 6) & 0x7) as u8).try_into().unwrap();
654            let rn: Register = (((input >> 3) & 0x7) as u8).try_into().unwrap();
655            let rd: Register = ((input & 0x7) as u8).try_into().unwrap();
656            Ok(Operation::SUBReg {
657                m: rm,
658                n: rn,
659                d: rd,
660            })
661        }
662        0b01110 => {
663            // ADD 3bit imm
664            let imm = (input >> 6) & 0x7;
665            let rn: Register = (((input >> 3) & 0x7) as u8).try_into().unwrap();
666            let rd: Register = ((input & 0x7) as u8).try_into().unwrap();
667            Ok(Operation::ADDImm {
668                imm: imm as u32,
669                n: rn,
670                d: rd,
671            })
672        }
673        0b01111 => {
674            // SUB 3bit imm
675            let imm: Register = (((input >> 6) & 0x7) as u8).try_into().unwrap();
676            let rn: Register = (((input >> 3) & 0x7) as u8).try_into().unwrap();
677            let rd: Register = ((input & 0x7) as u8).try_into().unwrap();
678            Ok(Operation::SUBImm {
679                imm: imm as u32,
680                n: rn,
681                d: rd,
682            })
683        }
684        0b10000..=0b10011 => {
685            // MOV imm
686            let imm = input & 0xff;
687            let rd: Register = (((input >> 8) & 0x7) as u8).try_into().unwrap();
688            Ok(Operation::MOVImm {
689                d: rd,
690                imm: imm as u32,
691            })
692        }
693        0b10100..=0b10111 => {
694            // CMP imm
695            let imm = input & 0xff;
696            let rn: Register = (((input >> 8) & 0x7) as u8).try_into().unwrap();
697            Ok(Operation::CMPImm {
698                n: rn,
699                imm: imm as u32,
700            })
701        }
702        0b11000..=0b11011 => {
703            // ADD 8bit imm
704            let imm = input & 0xff;
705            let rdn: Register = (((input >> 8) & 0x7) as u8).try_into().unwrap();
706            Ok(Operation::ADDImm {
707                imm: imm as u32,
708                n: rdn,
709                d: rdn,
710            })
711        }
712        0b11100..=0b11111 => {
713            // SUB 8bit imm
714            let imm = input & 0xff;
715            let rdn: Register = (((input >> 8) & 0x7) as u8).try_into().unwrap();
716            Ok(Operation::SUBImm {
717                n: rdn,
718                d: rdn,
719                imm: imm as u32,
720            })
721        }
722        _ => Err("Not a valid opcode"),
723    }
724}
725
726fn parse_misc_16_bit(input: u16) -> Result<Operation, &'static str> {
727    let opcode = (input >> 5) & 0x7f;
728    match opcode {
729        0b0000000..=0b0000011 => {
730            // ADD SP plus immediate
731            // A6-111
732            let imm = (input & 0x7f) << 2;
733            Ok(Operation::ADDImmSP {
734                d: Register::SP,
735                imm: imm as u32,
736            })
737        }
738        0b0000100..=0b0000111 => {
739            // SUB SP minus immediate
740            // A6-188
741            let imm = (input & 0x7f) << 2;
742            Ok(Operation::SUBImmSP { imm: imm as u32 })
743        }
744        0b0010000..=0b0010001 => {
745            // A6-191
746            // SXTH
747            let rm: Register = (((input >> 3) & 0x7) as u8).try_into().unwrap();
748            let rd: Register = ((input & 0x7) as u8).try_into().unwrap();
749
750            Ok(Operation::SXTH { m: rm, d: rd })
751        }
752        0b0010010..=0b0010011 => {
753            // A6-190
754            // SXTB
755            let rm: Register = (((input >> 3) & 0x7) as u8).try_into().unwrap();
756            let rd: Register = ((input & 0x7) as u8).try_into().unwrap();
757
758            Ok(Operation::SXTB { m: rm, d: rd })
759        }
760        0b0010100..=0b0010101 => {
761            // A6-196
762            // UXTH
763            let rm: Register = (((input >> 3) & 0x7) as u8).try_into().unwrap();
764            let rd: Register = ((input & 0x7) as u8).try_into().unwrap();
765
766            Ok(Operation::UXTH { m: rm, d: rd })
767        }
768        0b0010110..=0b0010111 => {
769            // A6-195
770            // UXTB
771            let rm: Register = (((input >> 3) & 0x7) as u8).try_into().unwrap();
772            let rd: Register = ((input & 0x7) as u8).try_into().unwrap();
773
774            Ok(Operation::UXTB { m: rm, d: rd })
775        }
776        0b0100000..=0b0101111 => {
777            // PUSH
778            // A6-167
779            let reg_list_bits = (((input >> 8) & 0b1) << 14) | (input & 0xff);
780            let reg_list = register_list_from_bit_array(reg_list_bits);
781            Ok(Operation::PUSH { reg_list: reg_list })
782        }
783        0b0110011 => {
784            // B4-306
785            // CPS
786            let im = ((input >> 4) & 0b1) == 1;
787            Ok(Operation::CPS { im: im })
788        }
789        0b1010000..=0b1010001 => {
790            // A6-168
791            // REV
792            let rm: Register = (((input >> 3) & 0x7) as u8).try_into().unwrap();
793            let rd: Register = ((input & 0x7) as u8).try_into().unwrap();
794
795            Ok(Operation::REV { m: rm, d: rd })
796        }
797        0b1010010..=0b1010011 => {
798            // A6-169
799            // REV16
800            let rm: Register = (((input >> 3) & 0x7) as u8).try_into().unwrap();
801            let rd: Register = ((input & 0x7) as u8).try_into().unwrap();
802
803            Ok(Operation::REV16 { m: rm, d: rd })
804        }
805        0b1010110..=0b1010111 => {
806            // A6-170
807            // REVSH
808            let rm: Register = (((input >> 3) & 0x7) as u8).try_into().unwrap();
809            let rd: Register = ((input & 0x7) as u8).try_into().unwrap();
810
811            Ok(Operation::REVSH { m: rm, d: rd })
812        }
813        0b1100000..=0b1101111 => {
814            // A6-165
815            // POP
816            let reg_list_bits = (((input >> 8) & 0b1) << 15) | (input & 0xff);
817            let reg_list = register_list_from_bit_array(reg_list_bits);
818            Ok(Operation::POP { reg_list: reg_list })
819        }
820        0b1110000..=0b1110111 => {
821            // A6-122
822            // BKPT
823            let imm = input & 0xff;
824            Ok(Operation::BKPT { imm: imm as u32 })
825        }
826        0b1111000..=0b1111111 => {
827            // A5-90
828            // Hint instruction
829            parse_hint_instruction(input)
830        }
831        _ => Err("invalid opcode"),
832    }
833}
834
835fn parse_hint_instruction(input: u16) -> Result<Operation, &'static str> {
836    // A5-90
837    let op_a = (input >> 4) & 0xf;
838    let op_b = input & 0xf;
839
840    if op_b > 0 {
841        return Err("invalid opcode");
842    }
843
844    match op_a {
845        0b0000 => Ok(Operation::NOP),
846        0b0001 => Ok(Operation::YIELD),
847        0b0010 => Ok(Operation::WFE),
848        0b0011 => Ok(Operation::WFE),
849        0b0100 => Ok(Operation::SEV),
850        _ => Err("invalid opcode"),
851    }
852}
853
854trait SignExtend {
855    fn sign_extend(&self, valid_bits: usize) -> u32;
856}
857
858impl SignExtend for u16 {
859    fn sign_extend(&self, valid_bits: usize) -> u32 {
860        let shift = 16 - valid_bits;
861        ((((self << shift) as i16) >> shift) as i32) as u32
862    }
863}
864
865impl SignExtend for u32 {
866    fn sign_extend(&self, valid_bits: usize) -> u32 {
867        let shift = 32 - valid_bits;
868        (((self << shift) as i32) >> shift) as u32
869    }
870}
871
872#[cfg(test)]
873mod test {
874    use super::*;
875
876    #[test]
877    fn sign_extend_u16() {
878        assert_eq!(0xffffffff, 0x1u16.sign_extend(1));
879        assert_eq!(0x1, 0x1u16.sign_extend(2));
880        assert_eq!(0xfffffff9, 0x9u16.sign_extend(4));
881        assert_eq!(0x00000009, 0x9u16.sign_extend(5));
882    }
883
884    #[test]
885    fn sign_extend_u32() {
886        assert_eq!(0xffffffff, 0x1u32.sign_extend(1));
887        assert_eq!(0x1, 0x1u32.sign_extend(2));
888        assert_eq!(0xfffffff9, 0x9u32.sign_extend(4));
889        assert_eq!(0x00000009, 0x9u32.sign_extend(5));
890    }
891}