Skip to main content

charm/core/a32/
operand.rs

1//! Instruction operands.
2
3use crate::error::*;
4
5// ------------------------------------------------------------------------------------------------
6// Operand
7// ------------------------------------------------------------------------------------------------
8
9/// Type that represent an instruction operand.
10#[derive(Copy, Clone, Eq, PartialEq, Ord, PartialOrd, Debug, Hash)]
11pub enum Operand {
12    None,
13    MnemonicCondition(MnemonicCondition),
14    AddressMode(AddressMode),
15    Condition(Condition),
16    ConditionalInstruction(ConditionalInstruction),
17    ItCondition(ItCondition),
18    Register(Register),
19    SpecialRegister(SpecialRegister),
20    BankedRegister(BankedRegister),
21    RegisterList(RegisterList),
22    SignedImmediate(i32),
23    UnsignedImmediate(u32),
24    ModifiedImmediate(ModifiedImmediate),
25    Label(Label),
26    Shift(Shift),
27    ShiftType(ShiftType),
28    Iflags(Iflags),
29    BarrierOperation(BarrierOperation),
30    PlusMinus(PlusMinus),
31    WriteBack(WriteBack),
32    SysRegEncodingSpace(SysRegEncodingSpace),
33    SysRegRegister(SysRegRegister),
34    ApsrNzcv,
35    Endianness(Endianness),
36}
37
38impl Operand {
39    pub fn is_none(&self) -> bool {
40        if let Operand::None = self {
41            return true;
42        }
43        false
44    }
45
46    pub fn as_mnemonic_condition(&self) -> Result<&MnemonicCondition> {
47        if let Operand::MnemonicCondition(value) = self {
48            return Ok(value);
49        }
50        todo!()
51    }
52
53    pub fn as_address_mode(&self) -> Result<&AddressMode> {
54        if let Operand::AddressMode(value) = self {
55            return Ok(value);
56        }
57        todo!()
58    }
59
60    pub fn as_condition(&self) -> Result<&Condition> {
61        if let Operand::Condition(value) = self {
62            return Ok(value);
63        }
64        todo!()
65    }
66
67    pub fn as_it_condition(&self) -> Result<&ItCondition> {
68        if let Operand::ItCondition(value) = self {
69            return Ok(value);
70        }
71        todo!()
72    }
73
74    pub fn as_register(&self) -> Result<&Register> {
75        if let Operand::Register(value) = self {
76            return Ok(value);
77        }
78        todo!()
79    }
80
81    pub fn as_special_register(&self) -> Result<&SpecialRegister> {
82        if let Operand::SpecialRegister(value) = self {
83            return Ok(value);
84        }
85        todo!()
86    }
87
88    pub fn as_banked_register(&self) -> Result<&BankedRegister> {
89        if let Operand::BankedRegister(value) = self {
90            return Ok(value);
91        }
92        todo!()
93    }
94
95    pub fn as_register_list(&self) -> Result<&RegisterList> {
96        if let Operand::RegisterList(value) = self {
97            return Ok(value);
98        }
99        todo!()
100    }
101
102    pub fn as_signed_immediate(&self) -> Result<i32> {
103        if let Operand::SignedImmediate(value) = self {
104            return Ok(*value);
105        }
106        todo!()
107    }
108
109    pub fn as_unsigned_immediate(&self) -> Result<u32> {
110        if let Operand::UnsignedImmediate(uimm) = self {
111            return Ok(*uimm);
112        }
113        if let Operand::SignedImmediate(uimm) = self {
114            return Ok(*uimm as u32);
115        }
116        todo!()
117    }
118
119    pub fn as_label(&self) -> Result<&Label> {
120        if let Operand::Label(value) = self {
121            return Ok(value);
122        }
123        todo!()
124    }
125
126    pub fn as_modified_immediate(&self) -> Result<&ModifiedImmediate> {
127        if let Operand::ModifiedImmediate(value) = self {
128            return Ok(value);
129        }
130        todo!()
131    }
132
133    pub fn as_shift(&self) -> Result<&Shift> {
134        if let Operand::Shift(value) = self {
135            return Ok(value);
136        }
137        todo!()
138    }
139
140    pub fn as_shift_type(&self) -> Result<&ShiftType> {
141        if let Operand::ShiftType(value) = self {
142            return Ok(value);
143        }
144        todo!()
145    }
146
147    pub fn as_iflags(&self) -> Result<&Iflags> {
148        if let Operand::Iflags(value) = self {
149            return Ok(value);
150        }
151        todo!()
152    }
153
154    pub fn as_barrier_operation(&self) -> Result<&BarrierOperation> {
155        if let Operand::BarrierOperation(value) = self {
156            return Ok(value);
157        }
158        todo!()
159    }
160
161    pub fn as_plus_minus(&self) -> Result<&PlusMinus> {
162        if let Operand::PlusMinus(value) = self {
163            return Ok(value);
164        }
165        todo!()
166    }
167
168    pub fn as_write_back(&self) -> Result<&WriteBack> {
169        if let Operand::WriteBack(value) = self {
170            return Ok(value);
171        }
172        todo!()
173    }
174
175    pub fn as_sysreg_encoding_space(&self) -> Result<&SysRegEncodingSpace> {
176        if let Operand::SysRegEncodingSpace(value) = self {
177            return Ok(value);
178        }
179        todo!()
180    }
181
182    pub fn as_sysreg_register(&self) -> Result<&SysRegRegister> {
183        if let Operand::SysRegRegister(value) = self {
184            return Ok(value);
185        }
186        todo!()
187    }
188
189    pub fn as_endianness(&self) -> Result<&Endianness> {
190        if let Operand::Endianness(value) = self {
191            return Ok(value);
192        }
193        todo!()
194    }
195}
196
197impl Default for Operand {
198    fn default() -> Self {
199        Operand::None
200    }
201}
202
203impl From<MnemonicCondition> for Operand {
204    fn from(value: MnemonicCondition) -> Self {
205        Operand::MnemonicCondition(value)
206    }
207}
208
209impl From<AddressMode> for Operand {
210    fn from(value: AddressMode) -> Self {
211        Operand::AddressMode(value)
212    }
213}
214
215impl From<Condition> for Operand {
216    fn from(value: Condition) -> Self {
217        Operand::Condition(value)
218    }
219}
220
221impl From<ItCondition> for Operand {
222    fn from(value: ItCondition) -> Self {
223        Operand::ItCondition(value)
224    }
225}
226
227impl From<Register> for Operand {
228    fn from(value: Register) -> Self {
229        Operand::Register(value)
230    }
231}
232
233impl From<SpecialRegister> for Operand {
234    fn from(value: SpecialRegister) -> Self {
235        Operand::SpecialRegister(value)
236    }
237}
238
239impl From<BankedRegister> for Operand {
240    fn from(value: BankedRegister) -> Self {
241        Operand::BankedRegister(value)
242    }
243}
244
245impl From<RegisterList> for Operand {
246    fn from(value: RegisterList) -> Self {
247        Operand::RegisterList(value)
248    }
249}
250
251impl From<&[Register]> for Operand {
252    fn from(value: &[Register]) -> Self {
253        let value = value
254            .iter()
255            .fold(0, |acc, register| acc | (1 << *register as usize));
256        Operand::RegisterList(RegisterList::decode(value))
257    }
258}
259
260impl From<u32> for Operand {
261    fn from(value: u32) -> Self {
262        Operand::UnsignedImmediate(value)
263    }
264}
265
266impl From<i32> for Operand {
267    fn from(value: i32) -> Self {
268        Operand::SignedImmediate(value)
269    }
270}
271
272impl From<ModifiedImmediate> for Operand {
273    fn from(value: ModifiedImmediate) -> Self {
274        Operand::ModifiedImmediate(value)
275    }
276}
277
278impl From<Label> for Operand {
279    fn from(value: Label) -> Self {
280        Operand::Label(value)
281    }
282}
283
284impl From<Shift> for Operand {
285    fn from(value: Shift) -> Self {
286        Operand::Shift(value)
287    }
288}
289
290impl From<ShiftType> for Operand {
291    fn from(value: ShiftType) -> Self {
292        Operand::ShiftType(value)
293    }
294}
295
296impl From<Iflags> for Operand {
297    fn from(value: Iflags) -> Self {
298        Operand::Iflags(value)
299    }
300}
301
302impl From<BarrierOperation> for Operand {
303    fn from(value: BarrierOperation) -> Self {
304        Operand::BarrierOperation(value)
305    }
306}
307
308impl From<PlusMinus> for Operand {
309    fn from(value: PlusMinus) -> Self {
310        Operand::PlusMinus(value)
311    }
312}
313
314impl From<WriteBack> for Operand {
315    fn from(value: WriteBack) -> Self {
316        Operand::WriteBack(value)
317    }
318}
319
320impl From<SysRegEncodingSpace> for Operand {
321    fn from(value: SysRegEncodingSpace) -> Self {
322        Operand::SysRegEncodingSpace(value)
323    }
324}
325
326impl From<SysRegRegister> for Operand {
327    fn from(value: SysRegRegister) -> Self {
328        Operand::SysRegRegister(value)
329    }
330}
331
332impl From<Endianness> for Operand {
333    fn from(value: Endianness) -> Self {
334        Operand::Endianness(value)
335    }
336}
337
338// ------------------------------------------------------------------------------------------------
339// Assembler Syntax
340// ------------------------------------------------------------------------------------------------
341
342#[derive(Copy, Clone, Eq, PartialEq, Ord, PartialOrd, Debug, Hash)]
343pub enum MnemonicCondition {
344    Eq,
345    Ne,
346    Cs,
347    Cc,
348    Mi,
349    Pl,
350    Vs,
351    Vc,
352    Hi,
353    Ls,
354    Ge,
355    Lt,
356    Gt,
357    Le,
358    Al,
359}
360
361impl MnemonicCondition {
362    pub fn decode(value: u32) -> Result<Self> {
363        match value {
364            0b0000 => Ok(Self::Eq),
365            0b0001 => Ok(Self::Ne),
366            0b0010 => Ok(Self::Cs),
367            0b0011 => Ok(Self::Cc),
368            0b0100 => Ok(Self::Mi),
369            0b0101 => Ok(Self::Pl),
370            0b0110 => Ok(Self::Vs),
371            0b0111 => Ok(Self::Vc),
372            0b1000 => Ok(Self::Hi),
373            0b1001 => Ok(Self::Ls),
374            0b1010 => Ok(Self::Ge),
375            0b1011 => Ok(Self::Lt),
376            0b1100 => Ok(Self::Gt),
377            0b1101 => Ok(Self::Le),
378            0b1110 => Ok(Self::Al),
379            _ => Err(OperandError::MnemonicConditionOutOfRange(value))?,
380        }
381    }
382
383    pub fn encode(self) -> u32 {
384        match self {
385            Self::Eq => 0b0000,
386            Self::Ne => 0b0001,
387            Self::Cs => 0b0010,
388            Self::Cc => 0b0011,
389            Self::Mi => 0b0100,
390            Self::Pl => 0b0101,
391            Self::Vs => 0b0110,
392            Self::Vc => 0b0111,
393            Self::Hi => 0b1000,
394            Self::Ls => 0b1001,
395            Self::Ge => 0b1010,
396            Self::Lt => 0b1011,
397            Self::Gt => 0b1100,
398            Self::Le => 0b1101,
399            Self::Al => 0b1110,
400        }
401    }
402
403    pub fn as_str(&self) -> &str {
404        match self {
405            Self::Eq => "eq",
406            Self::Ne => "ne",
407            Self::Cs => "hs",
408            Self::Cc => "lo",
409            Self::Mi => "mi",
410            Self::Pl => "pl",
411            Self::Vs => "vs",
412            Self::Vc => "vc",
413            Self::Hi => "hi",
414            Self::Ls => "ls",
415            Self::Ge => "ge",
416            Self::Lt => "lt",
417            Self::Gt => "gt",
418            Self::Le => "le",
419            Self::Al => "al",
420        }
421    }
422}
423
424#[derive(Copy, Clone, Eq, PartialEq, Ord, PartialOrd, Debug, Hash)]
425pub enum AddressMode {
426    DecrementAfter,
427    FullAscending,
428    DecrementBefore,
429    EmptyAscending,
430    IncrementAfter,
431    FullDescending,
432    IncrementBefore,
433    EmptyDescending,
434}
435
436#[allow(non_upper_case_globals)]
437impl AddressMode {
438    pub const DA: Self = Self::DecrementAfter;
439    pub const FA: Self = Self::FullAscending;
440    pub const DB: Self = Self::DecrementBefore;
441    pub const EA: Self = Self::EmptyAscending;
442    pub const IA: Self = Self::IncrementAfter;
443    pub const FD: Self = Self::FullDescending;
444    pub const IB: Self = Self::IncrementBefore;
445    pub const ED: Self = Self::EmptyDescending;
446
447    pub fn decode(value: u32) -> Self {
448        match (value & 2, value & 1) {
449            (0, 0) => Self::DecrementAfter,
450            (0, 1) => Self::DecrementBefore,
451            (2, 0) => Self::IncrementAfter,
452            (2, 1) => Self::IncrementBefore,
453            _ => unreachable!(),
454        }
455    }
456
457    pub fn encode(self) -> u32 {
458        match self {
459            Self::DecrementAfter => 0,
460            Self::FullAscending => 0,
461            Self::DecrementBefore => 1,
462            Self::EmptyAscending => 1,
463            Self::IncrementAfter => 2,
464            Self::FullDescending => 2,
465            Self::IncrementBefore => 3,
466            Self::EmptyDescending => 3,
467        }
468    }
469
470    pub fn as_str(self) -> &'static str {
471        match self {
472            Self::DecrementAfter => "da",
473            Self::FullAscending => "fa",
474            Self::DecrementBefore => "db",
475            Self::EmptyAscending => "ea",
476            Self::IncrementAfter => "ia",
477            Self::FullDescending => "fd",
478            Self::IncrementBefore => "ib",
479            Self::EmptyDescending => "ed",
480        }
481    }
482}
483
484#[derive(Copy, Clone, Eq, PartialEq, Ord, PartialOrd, Debug, Hash)]
485pub enum AssemblerQualifier {
486    None,
487    Narrow,
488    Wide,
489}
490
491#[derive(Copy, Clone, Eq, PartialEq, Ord, PartialOrd, Debug, Hash)]
492pub enum PlusMinus {
493    Plus,
494    Minus,
495}
496
497impl PlusMinus {
498    pub fn decode(value: u32) -> Self {
499        match value {
500            0 => Self::Minus,
501            _ => Self::Plus,
502        }
503    }
504
505    pub fn encode(self) -> u32 {
506        match self {
507            Self::Minus => 0,
508            Self::Plus => 1,
509        }
510    }
511}
512
513#[derive(Copy, Clone, Eq, PartialEq, Ord, PartialOrd, Debug, Hash)]
514pub enum WriteBack {
515    True,
516    False,
517}
518
519impl WriteBack {
520    pub fn decode(value: u32) -> Self {
521        match value {
522            1 => Self::True,
523            _ => Self::False,
524        }
525    }
526
527    pub fn encode(self) -> u32 {
528        match self {
529            Self::False => 0,
530            Self::True => 1,
531        }
532    }
533}
534
535// ------------------------------------------------------------------------------------------------
536// Register
537// ------------------------------------------------------------------------------------------------
538
539#[derive(Copy, Clone, Eq, PartialEq, Ord, PartialOrd, Debug, Hash)]
540pub enum Register {
541    R0,
542    R1,
543    R2,
544    R3,
545    R4,
546    R5,
547    R6,
548    R7,
549    R8,
550    R9,
551    R10,
552    R11,
553    R12,
554    R13,
555    R14,
556    R15,
557}
558
559impl Register {
560    pub const SP: Self = Self::R13;
561    pub const LR: Self = Self::R14;
562    pub const PC: Self = Self::R15;
563
564    pub fn decode(value: u32) -> Result<Self> {
565        match value {
566            0 => Ok(Self::R0),
567            1 => Ok(Self::R1),
568            2 => Ok(Self::R2),
569            3 => Ok(Self::R3),
570            4 => Ok(Self::R4),
571            5 => Ok(Self::R5),
572            6 => Ok(Self::R6),
573            7 => Ok(Self::R7),
574            8 => Ok(Self::R8),
575            9 => Ok(Self::R9),
576            10 => Ok(Self::R10),
577            11 => Ok(Self::R11),
578            12 => Ok(Self::R12),
579            13 => Ok(Self::R13),
580            14 => Ok(Self::R14),
581            15 => Ok(Self::R15),
582            _ => Err(OperandError::RegisterOutOfRange(value))?,
583        }
584    }
585
586    pub fn encode(self) -> u32 {
587        match self {
588            Self::R0 => 0,
589            Self::R1 => 1,
590            Self::R2 => 2,
591            Self::R3 => 3,
592            Self::R4 => 4,
593            Self::R5 => 5,
594            Self::R6 => 6,
595            Self::R7 => 7,
596            Self::R8 => 8,
597            Self::R9 => 9,
598            Self::R10 => 10,
599            Self::R11 => 11,
600            Self::R12 => 12,
601            Self::R13 => 13,
602            Self::R14 => 14,
603            Self::R15 => 15,
604        }
605    }
606
607    pub fn as_str(&self) -> &str {
608        match self {
609            Self::R0 => "r0",
610            Self::R1 => "r1",
611            Self::R2 => "r2",
612            Self::R3 => "r3",
613            Self::R4 => "r4",
614            Self::R5 => "r5",
615            Self::R6 => "r6",
616            Self::R7 => "r7",
617            Self::R8 => "r8",
618            Self::R9 => "r9",
619            Self::R10 => "r10",
620            Self::R11 => "r11",
621            Self::R12 => "r12",
622            Self::R13 => "sp",
623            Self::R14 => "lr",
624            Self::R15 => "pc",
625        }
626    }
627}
628
629#[allow(non_camel_case_types)]
630#[derive(Copy, Clone, Eq, PartialEq, Ord, PartialOrd, Debug, Hash)]
631pub enum SpecialRegister {
632    CPSR,
633    CPSR_c,
634    CPSR_x,
635    CPSR_xc,
636    CPSR_s,
637    CPSR_sc,
638    CPSR_sx,
639    CPSR_sxc,
640    CPSR_f,
641    CPSR_fc,
642    CPSR_fx,
643    CPSR_fxc,
644    CPSR_fs,
645    CPSR_fsc,
646    CPSR_fsx,
647    CPSR_fsxc,
648    SPSR,
649    SPSR_c,
650    SPSR_x,
651    SPSR_xc,
652    SPSR_s,
653    SPSR_sc,
654    SPSR_sx,
655    SPSR_sxc,
656    SPSR_f,
657    SPSR_fc,
658    SPSR_fx,
659    SPSR_fxc,
660    SPSR_fs,
661    SPSR_fsc,
662    SPSR_fsx,
663    SPSR_fsxc,
664    APSR,
665    APSR_nzcvq,
666    APSR_g,
667    APSR_nzcvqg,
668}
669
670impl SpecialRegister {
671    pub fn decode(r: u32, mask: u32, as_apsr: bool) -> Result<Self> {
672        let f = (mask >> 0) & 1;
673        let s = (mask >> 1) & 1;
674        let x = (mask >> 2) & 1;
675        let c = (mask >> 3) & 1;
676        Ok(match (r, c, x, s, f) {
677            (0, 0, 0, 0, 1) => Self::CPSR_c,
678            (0, 0, 0, 1, 0) => Self::CPSR_x,
679            (0, 0, 0, 1, 1) => Self::CPSR_xc,
680            (0, 0, 1, 0, 0) => {
681                if as_apsr {
682                    Self::APSR_g
683                } else {
684                    Self::CPSR_s
685                }
686            }
687            (0, 0, 1, 0, 1) => Self::CPSR_sc,
688            (0, 0, 1, 1, 0) => Self::CPSR_sx,
689            (0, 0, 1, 1, 1) => Self::CPSR_sxc,
690            (0, 1, 0, 0, 0) => {
691                if as_apsr {
692                    Self::APSR_nzcvq
693                } else {
694                    Self::CPSR_f
695                }
696            }
697            (0, 1, 0, 0, 1) => Self::CPSR_fc,
698            (0, 1, 0, 1, 0) => Self::CPSR_fx,
699            (0, 1, 0, 1, 1) => Self::CPSR_fxc,
700            (0, 1, 1, 0, 0) => {
701                if as_apsr {
702                    Self::APSR_nzcvqg
703                } else {
704                    Self::CPSR_fs
705                }
706            }
707            (0, 1, 1, 0, 1) => Self::CPSR_fsc,
708            (0, 1, 1, 1, 0) => Self::CPSR_fsx,
709            (0, 1, 1, 1, 1) => Self::CPSR_fsxc,
710            (1, 0, 0, 0, 0) => Self::SPSR,
711            (1, 0, 0, 0, 1) => Self::SPSR_c,
712            (1, 0, 0, 1, 0) => Self::SPSR_x,
713            (1, 0, 0, 1, 1) => Self::SPSR_xc,
714            (1, 0, 1, 0, 0) => Self::SPSR_s,
715            (1, 0, 1, 0, 1) => Self::SPSR_sc,
716            (1, 0, 1, 1, 0) => Self::SPSR_sx,
717            (1, 0, 1, 1, 1) => Self::SPSR_sxc,
718            (1, 1, 0, 0, 0) => Self::SPSR_f,
719            (1, 1, 0, 0, 1) => Self::SPSR_fc,
720            (1, 1, 0, 1, 0) => Self::SPSR_fx,
721            (1, 1, 0, 1, 1) => Self::SPSR_fxc,
722            (1, 1, 1, 0, 0) => Self::SPSR_fs,
723            (1, 1, 1, 0, 1) => Self::SPSR_fsc,
724            (1, 1, 1, 1, 0) => Self::SPSR_fsx,
725            (1, 1, 1, 1, 1) => Self::SPSR_fsxc,
726            x => todo!("{:#?}", x),
727        })
728    }
729
730    pub fn encode(self) -> Result<(u32, u32)> {
731        let (r, c, x, s, f) = match self {
732            Self::CPSR_c => (0, 0, 0, 0, 1),
733            Self::CPSR_x => (0, 0, 0, 1, 0),
734            Self::CPSR_xc => (0, 0, 0, 1, 1),
735            Self::CPSR_s | Self::APSR_g => (0, 0, 1, 0, 0),
736            Self::CPSR_sc => (0, 0, 1, 0, 1),
737            Self::CPSR_sx => (0, 0, 1, 1, 0),
738            Self::CPSR_sxc => (0, 0, 1, 1, 1),
739            Self::CPSR_f | Self::APSR_nzcvq => (0, 1, 0, 0, 0),
740            Self::CPSR_fc => (0, 1, 0, 0, 1),
741            Self::CPSR_fx => (0, 1, 0, 1, 0),
742            Self::CPSR_fxc => (0, 1, 0, 1, 1),
743            Self::CPSR_fs | Self::APSR_nzcvqg => (0, 1, 1, 0, 0),
744            Self::CPSR_fsc => (0, 1, 1, 0, 1),
745            Self::CPSR_fsx => (0, 1, 1, 1, 0),
746            Self::CPSR_fsxc => (0, 1, 1, 1, 1),
747            Self::SPSR => (1, 0, 0, 0, 0),
748            Self::SPSR_c => (1, 0, 0, 0, 1),
749            Self::SPSR_x => (1, 0, 0, 1, 0),
750            Self::SPSR_xc => (1, 0, 0, 1, 1),
751            Self::SPSR_s => (1, 0, 1, 0, 0),
752            Self::SPSR_sc => (1, 0, 1, 0, 1),
753            Self::SPSR_sx => (1, 0, 1, 1, 0),
754            Self::SPSR_sxc => (1, 0, 1, 1, 1),
755            Self::SPSR_f => (1, 1, 0, 0, 0),
756            Self::SPSR_fc => (1, 1, 0, 0, 1),
757            Self::SPSR_fx => (1, 1, 0, 1, 0),
758            Self::SPSR_fxc => (1, 1, 0, 1, 1),
759            Self::SPSR_fs => (1, 1, 1, 0, 0),
760            Self::SPSR_fsc => (1, 1, 1, 0, 1),
761            Self::SPSR_fsx => (1, 1, 1, 1, 0),
762            Self::SPSR_fsxc => (1, 1, 1, 1, 1),
763            x => todo!("{:#?}", x),
764        };
765        let mask = (c << 3) | (x << 2) | (s << 1) | f;
766        Ok((r, mask))
767    }
768
769    pub fn as_str(&self) -> &str {
770        match self {
771            Self::CPSR => "CPSR",
772            Self::CPSR_c => "CPSR_c",
773            Self::CPSR_x => "CPSR_x",
774            Self::CPSR_xc => "CPSR_xc",
775            Self::CPSR_s => "CPSR_s",
776            Self::CPSR_sc => "CPSR_sc",
777            Self::CPSR_sx => "CPSR_sx",
778            Self::CPSR_sxc => "CPSR_sxc",
779            Self::CPSR_f => "CPSR_f",
780            Self::CPSR_fc => "CPSR_fc",
781            Self::CPSR_fx => "CPSR_fx",
782            Self::CPSR_fxc => "CPSR_fxc",
783            Self::CPSR_fs => "CPSR_fs",
784            Self::CPSR_fsc => "CPSR_fsc",
785            Self::CPSR_fsx => "CPSR_fsx",
786            Self::CPSR_fsxc => "CPSR_fsxc",
787            Self::SPSR => "SPSR",
788            Self::SPSR_c => "SPSR_c",
789            Self::SPSR_x => "SPSR_x",
790            Self::SPSR_xc => "SPSR_xc",
791            Self::SPSR_s => "SPSR_s",
792            Self::SPSR_sc => "SPSR_sc",
793            Self::SPSR_sx => "SPSR_sx",
794            Self::SPSR_sxc => "SPSR_sxc",
795            Self::SPSR_f => "SPSR_f",
796            Self::SPSR_fc => "SPSR_fc",
797            Self::SPSR_fx => "SPSR_fx",
798            Self::SPSR_fxc => "SPSR_fxc",
799            Self::SPSR_fs => "SPSR_fs",
800            Self::SPSR_fsc => "SPSR_fsc",
801            Self::SPSR_fsx => "SPSR_fsx",
802            Self::SPSR_fsxc => "SPSR_fsxc",
803            Self::APSR => "APSR",
804            Self::APSR_nzcvq => "APSR_nzcvq",
805            Self::APSR_g => "APSR_g",
806            Self::APSR_nzcvqg => "APSR_nzcvqg",
807        }
808    }
809}
810
811#[derive(Copy, Clone, Eq, PartialEq, Ord, PartialOrd, Debug, Hash)]
812pub enum BankedRegister {
813    R8Usr,
814    R9Usr,
815    R10Usr,
816    R11Usr,
817    R12Usr,
818    SpUsr,
819    LrUsr,
820    R8Fiq,
821    R9Fiq,
822    R10Fiq,
823    R11Fiq,
824    R12Fiq,
825    SpFiq,
826    LrFiq,
827    LrIrq,
828    SpIrq,
829    LrSvc,
830    SpSvc,
831    LrAbt,
832    SpAbt,
833    LrUnd,
834    SpUnd,
835    LrMon,
836    SpMon,
837    ElrHyp,
838    SpHyp,
839    SpsrFiq,
840    SpsrIrq,
841    SpsrSvc,
842    SpsrAbt,
843    SpsrUnd,
844    SpsrMon,
845    SpsrHyp,
846}
847
848impl BankedRegister {
849    pub fn as_str(&self) -> &str {
850        match self {
851            Self::R8Usr => "r8_usr",
852            Self::R9Usr => "r9_usr",
853            Self::R10Usr => "r10_usr",
854            Self::R11Usr => "r11_usr",
855            Self::R12Usr => "r12_usr",
856            Self::SpUsr => "sp_usr",
857            Self::LrUsr => "lr_usr",
858            Self::R8Fiq => "r8_fiq",
859            Self::R9Fiq => "r9_fiq",
860            Self::R10Fiq => "r10_fiq",
861            Self::R11Fiq => "r11_fiq",
862            Self::R12Fiq => "r12_fiq",
863            Self::SpFiq => "sp_fiq",
864            Self::LrFiq => "lr_fiq",
865            Self::LrIrq => "lr_irq",
866            Self::SpIrq => "sp_irq",
867            Self::LrSvc => "lr_svc",
868            Self::SpSvc => "sp_svc",
869            Self::LrAbt => "lr_abt",
870            Self::SpAbt => "sp_abt",
871            Self::LrUnd => "lr_und",
872            Self::SpUnd => "sp_und",
873            Self::LrMon => "lr_mon",
874            Self::SpMon => "sp_mon",
875            Self::ElrHyp => "elr_hyp",
876            Self::SpHyp => "sp_hyp",
877            Self::SpsrFiq => "SPSR_fiq",
878            Self::SpsrIrq => "SPSR_irq",
879            Self::SpsrSvc => "SPSR_svc",
880            Self::SpsrAbt => "SPSR_abt",
881            Self::SpsrUnd => "SPSR_und",
882            Self::SpsrMon => "SPSR_mon",
883            Self::SpsrHyp => "SPSR_hyp",
884        }
885    }
886}
887
888#[derive(Copy, Clone, Eq, PartialEq, Ord, PartialOrd, Debug, Hash)]
889pub struct RegisterList(pub u16);
890
891impl RegisterList {
892    pub fn decode(value: u32) -> Self {
893        Self(value as u16)
894    }
895
896    pub fn encode(self) -> u32 {
897        self.0 as u32
898    }
899
900    pub fn value(self) -> Vec<Register> {
901        (0..16)
902            .into_iter()
903            .filter(|i| (self.0 >> i) & 1 == 1)
904            .fold(vec![], |mut acc, x| {
905                // Safety: it is ok to unwrap here, since the function only fails for values
906                // over 15 and we know this iterator won't go over it.
907                acc.push(Register::decode(x).unwrap());
908                acc
909            })
910    }
911}
912
913// ------------------------------------------------------------------------------------------------
914// Condition
915// ------------------------------------------------------------------------------------------------
916
917#[derive(Copy, Clone, Eq, PartialEq, Ord, PartialOrd, Debug, Hash)]
918pub enum Condition {
919    Eq,
920    Ne,
921    Cs,
922    Cc,
923    Mi,
924    Pl,
925    Vs,
926    Vc,
927    Hi,
928    Ls,
929    Ge,
930    Lt,
931    Gt,
932    Le,
933    Al,
934}
935
936impl Condition {
937    pub fn decode(value: u32) -> Result<Self> {
938        match value {
939            0b0000 => Ok(Self::Eq),
940            0b0001 => Ok(Self::Ne),
941            0b0010 => Ok(Self::Cs),
942            0b0011 => Ok(Self::Cc),
943            0b0100 => Ok(Self::Mi),
944            0b0101 => Ok(Self::Pl),
945            0b0110 => Ok(Self::Vs),
946            0b0111 => Ok(Self::Vc),
947            0b1000 => Ok(Self::Hi),
948            0b1001 => Ok(Self::Ls),
949            0b1010 => Ok(Self::Ge),
950            0b1011 => Ok(Self::Lt),
951            0b1100 => Ok(Self::Gt),
952            0b1101 => Ok(Self::Le),
953            0b1110 => Ok(Self::Al),
954            _ => Err(OperandError::ConditionOutOfRange(value))?,
955        }
956    }
957
958    pub fn encode(self) -> u32 {
959        match self {
960            Self::Eq => 0b0000,
961            Self::Ne => 0b0001,
962            Self::Cs => 0b0010,
963            Self::Cc => 0b0011,
964            Self::Mi => 0b0100,
965            Self::Pl => 0b0101,
966            Self::Vs => 0b0110,
967            Self::Vc => 0b0111,
968            Self::Hi => 0b1000,
969            Self::Ls => 0b1001,
970            Self::Ge => 0b1010,
971            Self::Lt => 0b1011,
972            Self::Gt => 0b1100,
973            Self::Le => 0b1101,
974            Self::Al => 0b1110,
975        }
976    }
977
978    pub fn opposite(self) -> Self {
979        match self {
980            Self::Eq => Self::Ne,
981            Self::Ne => Self::Eq,
982            Self::Cs => Self::Cc,
983            Self::Cc => Self::Cs,
984            Self::Mi => Self::Pl,
985            Self::Pl => Self::Mi,
986            Self::Vs => Self::Vc,
987            Self::Vc => Self::Vs,
988            Self::Hi => Self::Ls,
989            Self::Ls => Self::Hi,
990            Self::Ge => Self::Lt,
991            Self::Lt => Self::Ge,
992            Self::Gt => Self::Le,
993            Self::Le => Self::Gt,
994            _ => todo!(),
995        }
996    }
997
998    pub fn as_str(&self) -> &str {
999        match self {
1000            Self::Eq => "eq",
1001            Self::Ne => "ne",
1002            Self::Cs => "hs",
1003            Self::Cc => "lo",
1004            Self::Mi => "mi",
1005            Self::Pl => "pl",
1006            Self::Vs => "vs",
1007            Self::Vc => "vc",
1008            Self::Hi => "hi",
1009            Self::Ls => "ls",
1010            Self::Ge => "ge",
1011            Self::Lt => "lt",
1012            Self::Gt => "gt",
1013            Self::Le => "le",
1014            Self::Al => "al",
1015        }
1016    }
1017}
1018
1019impl From<Condition> for MnemonicCondition {
1020    fn from(value: Condition) -> Self {
1021        match value {
1022            Condition::Eq => Self::Eq,
1023            Condition::Ne => Self::Ne,
1024            Condition::Cs => Self::Cs,
1025            Condition::Cc => Self::Cc,
1026            Condition::Mi => Self::Mi,
1027            Condition::Pl => Self::Pl,
1028            Condition::Vs => Self::Vs,
1029            Condition::Vc => Self::Vc,
1030            Condition::Hi => Self::Hi,
1031            Condition::Ls => Self::Ls,
1032            Condition::Ge => Self::Ge,
1033            Condition::Lt => Self::Lt,
1034            Condition::Gt => Self::Gt,
1035            Condition::Le => Self::Le,
1036            Condition::Al => Self::Al,
1037        }
1038    }
1039}
1040
1041#[derive(Copy, Clone, Eq, PartialEq, Ord, PartialOrd, Debug, Hash)]
1042pub enum ItCondition {
1043    None,
1044    If,
1045    Else,
1046}
1047
1048impl ItCondition {
1049    pub fn is_none(&self) -> bool {
1050        if let ItCondition::None = self {
1051            return true;
1052        }
1053        false
1054    }
1055
1056    pub fn decode(value: u32, firstcond: u32, position: u32) -> Result<Self> {
1057        // There is at most 4 conditions for an IT block and the first one is not handled by this
1058        // type.
1059        if position == 0 || position > 3 {
1060            todo!()
1061        }
1062        // The IT condition at `position` is omitted if the bits that follow the bit where the
1063        // condition is encoded are all zeroes.
1064        let shift = 4 - position;
1065        let mask = (1 << shift) - 1;
1066        if value & mask == 0 {
1067            return Ok(Self::None);
1068        } else if (value >> shift) & 1 == firstcond & 1 {
1069            return Ok(Self::If);
1070        } else {
1071            return Ok(Self::Else);
1072        }
1073    }
1074
1075    pub fn encode(self, firstcond: u32, position: u32) -> u32 {
1076        match self {
1077            Self::None => 1 << (4 - position),
1078            Self::If => (firstcond & 1) << (4 - position) | if position == 3 { 1 } else { 0 },
1079            Self::Else => {
1080                ((firstcond + 1) % 2) << (4 - position) | if position == 3 { 1 } else { 0 }
1081            }
1082        }
1083    }
1084
1085    pub fn as_str(&self) -> &str {
1086        match self {
1087            Self::None => "",
1088            Self::If => "t",
1089            Self::Else => "e",
1090        }
1091    }
1092}
1093
1094#[derive(Copy, Clone, Eq, PartialEq, Ord, PartialOrd, Debug, Hash)]
1095pub enum ConditionalInstruction {
1096    None,
1097    ItBlock(Condition, ItCondition, ItCondition, ItCondition),
1098    // Condition index and must it be last.
1099    Condition(usize, bool, bool),
1100}
1101
1102impl ConditionalInstruction {
1103    pub fn encode(self) -> (u32, u32) {
1104        match self {
1105            Self::ItBlock(cond, ic1, ic2, ic3) => {
1106                let firstcond = cond.encode();
1107                let mut mask = 0;
1108
1109                mask |= ic1.encode(firstcond, 1);
1110                if ic1.is_none() {
1111                    return (firstcond, mask);
1112                }
1113                mask |= ic2.encode(firstcond, 2);
1114                if ic2.is_none() {
1115                    return (firstcond, mask);
1116                }
1117                mask |= ic3.encode(firstcond, 3);
1118                return (firstcond, mask);
1119            }
1120            _ => todo!(),
1121        }
1122    }
1123}
1124
1125// ------------------------------------------------------------------------------------------------
1126// Immediate
1127// ------------------------------------------------------------------------------------------------
1128
1129#[derive(Copy, Clone, Eq, PartialEq, Ord, PartialOrd, Debug, Hash)]
1130pub struct ModifiedImmediate(pub u32, pub u32);
1131
1132impl ModifiedImmediate {
1133    pub fn decode(value: u32) -> Self {
1134        let rotation = (value >> 8) & 0xf;
1135        let value = value & 0xff;
1136        Self(rotation, value)
1137    }
1138
1139    pub fn encode(self) -> u32 {
1140        (self.0 << 8) | self.1
1141    }
1142
1143    pub fn value(self) -> u32 {
1144        self.1.rotate_right(self.0 * 2)
1145    }
1146}
1147
1148// ------------------------------------------------------------------------------------------------
1149// Label
1150// ------------------------------------------------------------------------------------------------
1151
1152#[derive(Copy, Clone, Eq, PartialEq, Ord, PartialOrd, Debug, Hash)]
1153pub enum Label {
1154    LabelName(u64),
1155    Label(i32),
1156    LabelModified(ModifiedImmediate),
1157    LabelModifiedNegative(ModifiedImmediate),
1158}
1159
1160impl Label {
1161    pub fn decode(value: i64, modified: bool) -> Self {
1162        if modified {
1163            if value < 0 {
1164                Self::LabelModifiedNegative(ModifiedImmediate::decode(-value as u32))
1165            } else {
1166                Self::LabelModified(ModifiedImmediate::decode(value as u32))
1167            }
1168        } else {
1169            Self::Label(value as i32)
1170        }
1171    }
1172
1173    pub fn encode(self) -> Result<u32> {
1174        match self {
1175            Self::Label(imm) => Ok(imm as u32),
1176            Self::LabelModified(imm) => Ok(imm.encode()),
1177            Self::LabelModifiedNegative(imm) => Ok(imm.encode()),
1178            Self::LabelName(_) => todo!(),
1179        }
1180    }
1181
1182    pub fn value(self) -> i64 {
1183        match self {
1184            Self::Label(imm) => imm as i64,
1185            Self::LabelModified(imm) => imm.value() as i64,
1186            Self::LabelModifiedNegative(imm) => -(imm.value() as i64),
1187            Self::LabelName(imm) => imm as i64,
1188        }
1189    }
1190}
1191
1192// ------------------------------------------------------------------------------------------------
1193// Shift
1194// ------------------------------------------------------------------------------------------------
1195
1196#[derive(Copy, Clone, Eq, PartialEq, Ord, PartialOrd, Debug, Hash)]
1197pub enum Shift {
1198    LSL(u32),
1199    LSR(u32),
1200    ASR(u32),
1201    ROR(u32),
1202    RRX,
1203}
1204
1205impl Shift {
1206    pub fn value(self) -> u32 {
1207        match self {
1208            Self::LSL(imm) => imm,
1209            Self::LSR(imm) => imm,
1210            Self::ASR(imm) => imm,
1211            Self::ROR(imm) => imm,
1212            Self::RRX => 1,
1213        }
1214    }
1215
1216    pub fn as_str(&self) -> &str {
1217        match self {
1218            Self::LSL(_) => "lsl",
1219            Self::LSR(_) => "lsr",
1220            Self::ASR(_) => "asr",
1221            Self::ROR(_) => "ror",
1222            Self::RRX => "rrx",
1223        }
1224    }
1225}
1226
1227#[derive(Copy, Clone, Eq, PartialEq, Ord, PartialOrd, Debug, Hash)]
1228pub enum ShiftType {
1229    LSL,
1230    LSR,
1231    ASR,
1232    ROR,
1233}
1234
1235impl ShiftType {
1236    pub fn as_str(&self) -> &str {
1237        match self {
1238            Self::LSL => "lsl",
1239            Self::LSR => "lsr",
1240            Self::ASR => "asr",
1241            Self::ROR => "ror",
1242        }
1243    }
1244}
1245
1246// ------------------------------------------------------------------------------------------------
1247// Operations
1248// ------------------------------------------------------------------------------------------------
1249
1250#[derive(Copy, Clone, Eq, PartialEq, Ord, PartialOrd, Debug, Hash)]
1251pub struct Iflags {
1252    pub a: bool,
1253    pub i: bool,
1254    pub f: bool,
1255}
1256
1257impl Iflags {
1258    pub fn decode(a: u32, i: u32, f: u32) -> Self {
1259        Self {
1260            a: a != 0,
1261            i: i != 0,
1262            f: f != 0,
1263        }
1264    }
1265
1266    pub fn encode(self) -> (u32, u32, u32) {
1267        (self.a as u32, self.i as u32, self.f as u32)
1268    }
1269}
1270
1271#[derive(Copy, Clone, Eq, PartialEq, Ord, PartialOrd, Debug, Hash)]
1272pub enum BarrierOperation {
1273    Ssbb,
1274    Pssbb,
1275    Sy,
1276    St,
1277    Ld,
1278    Ish,
1279    Ishst,
1280    Ishld,
1281    Nsh,
1282    Nshst,
1283    Nshld,
1284    Osh,
1285    Oshst,
1286    Oshld,
1287    Reserved(u8),
1288}
1289
1290impl BarrierOperation {
1291    pub fn decode_dsb(value: u32) -> Self {
1292        match value {
1293            0b0000 => Self::Ssbb,
1294            0b0001 => Self::Oshld,
1295            0b0010 => Self::Oshst,
1296            0b0011 => Self::Osh,
1297            0b0100 => Self::Pssbb,
1298            0b0101 => Self::Nshld,
1299            0b0110 => Self::Nshst,
1300            0b0111 => Self::Nsh,
1301            0b1001 => Self::Ishld,
1302            0b1010 => Self::Ishst,
1303            0b1011 => Self::Ish,
1304            0b1101 => Self::Ld,
1305            0b1110 => Self::St,
1306            0b1111 => Self::Sy,
1307            _ => Self::Reserved(value as u8),
1308        }
1309    }
1310
1311    pub fn decode_dmb(value: u32) -> Self {
1312        match value {
1313            0b0001 => Self::Oshld,
1314            0b0010 => Self::Oshst,
1315            0b0011 => Self::Osh,
1316            0b0101 => Self::Nshld,
1317            0b0110 => Self::Nshst,
1318            0b0111 => Self::Nsh,
1319            0b1001 => Self::Ishld,
1320            0b1010 => Self::Ishst,
1321            0b1011 => Self::Ish,
1322            0b1101 => Self::Ld,
1323            0b1110 => Self::St,
1324            0b1111 => Self::Sy,
1325            _ => Self::Reserved(value as u8),
1326        }
1327    }
1328
1329    pub fn decode_isb(value: u32) -> Self {
1330        match value {
1331            0b1111 => Self::Sy,
1332            _ => Self::Reserved(value as u8),
1333        }
1334    }
1335
1336    pub fn encode(self) -> u32 {
1337        match self {
1338            Self::Ssbb => 0b0000,
1339            Self::Oshld => 0b0001,
1340            Self::Oshst => 0b0010,
1341            Self::Osh => 0b0011,
1342            Self::Pssbb => 0b0100,
1343            Self::Nshld => 0b0101,
1344            Self::Nshst => 0b0110,
1345            Self::Nsh => 0b0111,
1346            Self::Ishld => 0b1001,
1347            Self::Ishst => 0b1010,
1348            Self::Ish => 0b1011,
1349            Self::Ld => 0b1101,
1350            Self::St => 0b1110,
1351            Self::Sy => 0b1111,
1352            Self::Reserved(x) => x as u32,
1353        }
1354    }
1355
1356    pub fn as_str(&self) -> &str {
1357        match self {
1358            Self::Ssbb => "ssbb",
1359            Self::Oshld => "oshld",
1360            Self::Oshst => "oshst",
1361            Self::Osh => "osh",
1362            Self::Pssbb => "pssbb",
1363            Self::Nshld => "nshld",
1364            Self::Nshst => "nshst",
1365            Self::Nsh => "nsh",
1366            Self::Ishld => "ishld",
1367            Self::Ishst => "ishst",
1368            Self::Ish => "ish",
1369            Self::Ld => "ld",
1370            Self::St => "st",
1371            Self::Sy => "sy",
1372            Self::Reserved(_) => "reserved",
1373        }
1374    }
1375}
1376
1377#[derive(Copy, Clone, Eq, PartialEq, Ord, PartialOrd, Debug, Hash)]
1378pub enum SysRegEncodingSpace {
1379    P14,
1380    P15,
1381}
1382
1383impl SysRegEncodingSpace {
1384    pub fn decode(value: u32) -> Result<Self> {
1385        Ok(match value {
1386            0 => Self::P14,
1387            1 => Self::P15,
1388            _ => todo!(),
1389        })
1390    }
1391
1392    pub fn encode(self) -> u32 {
1393        match self {
1394            Self::P14 => 0,
1395            Self::P15 => 1,
1396        }
1397    }
1398
1399    pub fn as_str(&self) -> &str {
1400        match self {
1401            Self::P14 => "p14",
1402            Self::P15 => "p15",
1403        }
1404    }
1405}
1406
1407#[derive(Copy, Clone, Eq, PartialEq, Ord, PartialOrd, Debug, Hash)]
1408pub enum SysRegRegister {
1409    C0,
1410    C1,
1411    C2,
1412    C3,
1413    C4,
1414    C5,
1415    C6,
1416    C7,
1417    C8,
1418    C9,
1419    C10,
1420    C11,
1421    C12,
1422    C13,
1423    C14,
1424    C15,
1425}
1426
1427impl SysRegRegister {
1428    pub fn decode(value: u32) -> Result<Self> {
1429        match value {
1430            0 => Ok(Self::C0),
1431            1 => Ok(Self::C1),
1432            2 => Ok(Self::C2),
1433            3 => Ok(Self::C3),
1434            4 => Ok(Self::C4),
1435            5 => Ok(Self::C5),
1436            6 => Ok(Self::C6),
1437            7 => Ok(Self::C7),
1438            8 => Ok(Self::C8),
1439            9 => Ok(Self::C9),
1440            10 => Ok(Self::C10),
1441            11 => Ok(Self::C11),
1442            12 => Ok(Self::C12),
1443            13 => Ok(Self::C13),
1444            14 => Ok(Self::C14),
1445            15 => Ok(Self::C15),
1446            _ => Err(OperandError::RegisterOutOfRange(value))?,
1447        }
1448    }
1449
1450    pub fn encode(self) -> u32 {
1451        match self {
1452            Self::C0 => 0,
1453            Self::C1 => 1,
1454            Self::C2 => 2,
1455            Self::C3 => 3,
1456            Self::C4 => 4,
1457            Self::C5 => 5,
1458            Self::C6 => 6,
1459            Self::C7 => 7,
1460            Self::C8 => 8,
1461            Self::C9 => 9,
1462            Self::C10 => 10,
1463            Self::C11 => 11,
1464            Self::C12 => 12,
1465            Self::C13 => 13,
1466            Self::C14 => 14,
1467            Self::C15 => 15,
1468        }
1469    }
1470
1471    pub fn as_str(&self) -> &str {
1472        match self {
1473            Self::C0 => "c0",
1474            Self::C1 => "c1",
1475            Self::C2 => "c2",
1476            Self::C3 => "c3",
1477            Self::C4 => "c4",
1478            Self::C5 => "c5",
1479            Self::C6 => "c6",
1480            Self::C7 => "c7",
1481            Self::C8 => "c8",
1482            Self::C9 => "c9",
1483            Self::C10 => "c10",
1484            Self::C11 => "c11",
1485            Self::C12 => "c12",
1486            Self::C13 => "c13",
1487            Self::C14 => "c14",
1488            Self::C15 => "c15",
1489        }
1490    }
1491}
1492
1493#[derive(Copy, Clone, Eq, PartialEq, Ord, PartialOrd, Debug, Hash)]
1494pub enum Endianness {
1495    Le,
1496    Be,
1497}
1498
1499impl Endianness {
1500    pub fn decode(value: u32) -> Result<Self> {
1501        match value {
1502            0 => Ok(Self::Le),
1503            1 => Ok(Self::Be),
1504            _ => todo!(),
1505        }
1506    }
1507
1508    pub fn encode(self) -> u32 {
1509        match self {
1510            Self::Le => 0,
1511            Self::Be => 1,
1512        }
1513    }
1514
1515    pub fn as_str(&self) -> &str {
1516        match self {
1517            Self::Le => "le",
1518            Self::Be => "be",
1519        }
1520    }
1521}