armv4t/operation.rs
1use types::{MultiplyFlags, TransferFlags};
2
3descriminant! {
4 #[doc = "
5Condition codes for controlling execution
6
7Variants, values and conditions are as follows:
8
9| Variant | Value | Conditions |
10|---------------|-------|---------------------------|
11| `Equal` | `0x0` | `Z == true` |
12| `NotEqual` | `0x1` | `Z == false` |
13| `UnsignedGTE` | `0x2` | `C == true` |
14| `UnsignedLT` | `0x3` | `C == false` |
15| `Negative` | `0x4` | `N == true` |
16| `Positive` | `0x5` | `N == false` |
17| `Overflow` | `0x6` | `V == true` |
18| `NoOverflow` | `0x7` | `V == false` |
19| `UnsignedGT` | `0x8` | `C == true && Z == false` |
20| `UnsignedLTE` | `0x9` | `C == false && Z == true` |
21| `SignedGTE` | `0xa` | `N == V` |
22| `SignedLT` | `0xb` | `N != V` |
23| `SignedGT` | `0xc` | `Z == false && N == V` |
24| `SignedLTE` | `0xd` | `Z == true || N != V` |
25| `Always` | `0xe` | - |"]
26 #[derive(Clone, Copy, Debug, PartialEq)]
27 pub enum Condition<u32> {
28 #[doc = "Equal"]
29 Equal = 0x0,
30 #[doc = "Not equal"]
31 NotEqual = 0x1,
32 #[doc = "Greater than or equal (unsigned)"]
33 UnsignedGTE = 0x2,
34 #[doc = "Less than (unsigned)"]
35 UnsignedLT = 0x3,
36 #[doc = "Negative"]
37 Negative = 0x4,
38 #[doc = "Positive or zero"]
39 Positive = 0x5,
40 #[doc = "Overflow"]
41 Overflow = 0x6,
42 #[doc = "No overflow"]
43 NoOverflow = 0x7,
44 #[doc = "Greater than (unsigned)"]
45 UnsignedGT = 0x8,
46 #[doc = "Less than or equal (unsigned)"]
47 UnsignedLTE = 0x9,
48 #[doc = "Greater than or equal (signed)"]
49 SignedGTE = 0xa,
50 #[doc = "Less than (signed)"]
51 SignedLT = 0xb,
52 #[doc = "Greater than (signed)"]
53 SignedGT = 0xc,
54 #[doc = "Less than or equal (signed)"]
55 SignedLTE = 0xd,
56 #[doc = "Always"]
57 Always = 0xe
58 }
59}
60
61/// A collection of registers associated with an operation.
62#[derive(Clone, Copy, Debug, Default, PartialEq)]
63pub struct Registers {
64 /// The `d` register
65 pub d: u8,
66 /// The `h` register
67 pub h: u8,
68 /// The `l` register
69 pub l: u8,
70 /// The `m` register
71 pub m: u8,
72 /// The `n` register
73 pub n: u8,
74 /// The `s` register
75 pub s: u8,
76}
77
78/// A wrapper around a boolean that specifies whether to set condition
79/// codes.
80#[derive(Clone, Copy, Debug, PartialEq)]
81pub struct SetFlags(pub bool);
82
83impl From<bool> for SetFlags {
84 fn from(flag: bool) -> Self {
85 SetFlags(flag)
86 }
87}
88
89/// A wrapper around a boolean that specifies whether to set r14 on
90/// branching.
91#[derive(Clone, Copy, Debug, PartialEq)]
92pub struct Link(pub bool);
93
94impl From<bool> for Link {
95 fn from(flag: bool) -> Self {
96 Link(flag)
97 }
98}
99
100/// Processor operations
101///
102/// Operations that the processor can perform.
103#[derive(Clone, Copy, Debug, PartialEq)]
104pub enum Operation {
105 /// Data processing
106 ///
107 /// Perform an arithmetic or logical calculation on data contained
108 /// in registers or encoded in the instruction.
109 Alu(DataOp, SetFlags, Registers, Shift),
110 /// Status register transfer
111 ///
112 /// Perform a transfer of a value between a register and a status
113 /// register.
114 ///
115 /// __NOTE:__ The u8 member is the mask of the portions of the
116 /// status register that should be transferred.
117 StatusTransfer(TransferFlags, u8, Registers, Shift),
118 /// Multiply
119 ///
120 /// Perform integer multiplication on data contained in registers.
121 Multiply(MultiplyFlags, Registers),
122 /// Multiply long
123 ///
124 /// Perform integer multiplication on data contained in registers,
125 /// producing a 64-bit result.
126 MultiplyLong(MultiplyFlags, Registers),
127 /// Single Data Swap
128 ///
129 /// Perform a swap between a register and a memory address.
130 SingleDataSwap(TransferFlags, Registers),
131 /// Branch and Exchange
132 ///
133 /// Perform a branch by setting the program counter. The instruction
134 /// set can also be changed based on the contents of the new PC.
135 BranchExchange(Registers),
136 /// Halfword and signed data transfer
137 ///
138 /// Perform a transfer of a halfword, byte, signed halfword, or
139 /// signed halfword value between a register and memory.
140 HalfwordDataTransfer(TransferFlags, Registers, Shift),
141 /// Single data transfer
142 ///
143 /// Perform a transfer of a word, or byte value between a register
144 /// and memory.
145 SingleDataTransfer(TransferFlags, Registers, Shift),
146 /// Undefined
147 ///
148 /// Execute the undefined instruction trap.
149 Undefined,
150 /// Block data transfer
151 ///
152 /// Perform a transfer of a subset of visible registers between the
153 /// register bank and memory.
154 BlockDataTransfer(TransferFlags, Registers, u16),
155 /// Conditional branch
156 ///
157 /// Perform a branch by adding an offset to the program counter.
158 Branch(Condition, Link, i32),
159 /// Coprocessor data transfer
160 ///
161 /// Perform a transfer between a subset of a coprocessor's registers
162 /// and memory.
163 ///
164 /// __NOTE:__ The u8 member is the coprocessor number and the u32
165 /// member is the offset.
166 CoprocessorDataTransfer(TransferFlags, u8, Registers, u32),
167 /// Coprocessor data operation
168 ///
169 /// Perform a request for an operation on a coprocessor.
170 ///
171 /// __NOTE:__ The u8 members are, in order: coprocessor number,
172 /// coprocessor opcode, coprocessor information.
173 CoprocessorDataOperation(u8, u8, u8, Registers),
174 /// Coprocessor register transfer
175 ///
176 /// Perform a transfer between an ARM register and a coprocessor
177 /// register, with an optional transformation.
178 ///
179 /// __NOTE:__ The u8 members are, in order: coprocessor number,
180 /// coprocessor opcode, coprocessor information.
181 CoprocessorRegisterTransfer(TransferFlags, u8, u8, u8, Registers),
182 /// Software interrupt
183 ///
184 /// Execute the software interrupt trap.
185 SoftwareInterrupt(u32),
186}
187
188descriminant! {
189 #[doc = "
190Arithmetic/logical operations
191
192Variants, values and operations are as follows:
193
194| Variant | Value | Operation & Flags |
195|---------|-------|-----------------------------------------|
196| `And` | `0x0` | `lhs & rhs` sets N, Z; shift sets C |
197| `Eor` | `0x1` | `lhs ^ rhs` sets N, Z, shift sets C |
198| `Sub` | `0x2` | `lhs - rhs` sets N, Z, C, V |
199| `Rsb` | `0x3` | `rhs - lhs` sets N, Z, C, V |
200| `Add` | `0x4` | `lhs + rhs` sets N, Z, C, V |
201| `Adc` | `0x5` | `lhs + rhs + carry` sets N, Z, C, V |
202| `Sbc` | `0x6` | `lhs - rhs - 1 + carry` sets N, Z, C, V |
203| `Rsc` | `0x7` | `rhs - lhs - 1 + carry` sets N, Z, C, V |
204| `Tst` | `0x8` | `lhs & rhs` sets N, Z; shift sets C |
205| `Teq` | `0x9` | `lhs ^ rhs` sets N, Z; shift sets C |
206| `Cmp` | `0xa` | `lhs - rhs` sets N, Z, C, V |
207| `Cmn` | `0xb` | `lhs + rhs` sets N, Z, C, V |
208| `Orr` | `0xc` | `lhs | rhs` sets N, Z; shift sets C |
209| `Mov` | `0xd` | `rhs` sets N, Z; shift sets C |
210| `Bic` | `0xe` | `lhs & !rhs` sets N, Z; shift sets C |
211| `Mvn` | `0xf` | `!rhs` sets N, Z; shift sets C |"]
212 #[derive(Clone, Copy, Debug, PartialEq)]
213 pub enum DataOp<u32> {
214 #[doc = "And"]
215 And = 0x0,
216 #[doc = "Exclusive or"]
217 Eor = 0x1,
218 #[doc = "Subtract"]
219 Sub = 0x2,
220 #[doc = "Reverse subtract"]
221 Rsb = 0x3,
222 #[doc = "Add"]
223 Add = 0x4,
224 #[doc = "Add with carry"]
225 Adc = 0x5,
226 #[doc = "Subtract with carry"]
227 Sbc = 0x6,
228 #[doc = "Reverse subtract with carry"]
229 Rsc = 0x7,
230 #[doc = "Test"]
231 Tst = 0x8,
232 #[doc = "Test equal"]
233 Teq = 0x9,
234 #[doc = "Compare"]
235 Cmp = 0xa,
236 #[doc = "Compare negative"]
237 Cmn = 0xb,
238 #[doc = "Or"]
239 Orr = 0xc,
240 #[doc = "Move"]
241 Mov = 0xd,
242 #[doc = "Bit clear"]
243 Bic = 0xe,
244 #[doc = "Move negative"]
245 Mvn = 0xf
246 }
247}
248
249/// Barrel shift operations
250///
251/// Shift types are encoded as follows:
252///
253/// - `0b00`: logical left
254/// - `0b01`: logical right
255/// - `0b10`: arithmetic right
256/// - `0b11`: rotate right
257#[derive(Clone, Copy, Debug, PartialEq)]
258pub enum Shift {
259 /// Immediate value
260 ///
261 /// The value in the instruction is used unmodified.
262 Immediate {
263 /// Value
264 value: u32,
265 },
266 /// Immediate shifted register
267 ///
268 /// The value in register `rm` is shifted by the amount given in the
269 /// amount field.
270 ImmediateShiftedRegister {
271 /// Amount to shift the base value
272 amount: u8,
273 /// Type of shift to perform
274 shift: u8,
275 /// Register containing base value
276 m: u8
277 },
278 /// Register shifted register
279 ///
280 /// The value in register `rm` is shifted by the amount given in
281 /// register `rs`.
282 RegisterShiftedRegister {
283 /// Register containing the amount to shift
284 s: u8,
285 /// Type of shift to perform
286 shift: u8,
287 /// Register containing base value
288 m: u8
289 },
290 /// Rotated immediate value
291 ///
292 /// The immediate value is rotated by twice the amount given in the
293 /// rotate field.
294 RotatedImmediate {
295 /// Amount to rotate divided by two
296 rotation: u8,
297 /// Value to rotate
298 immediate: u8
299 },
300}