probe_rs/architecture/arm/core/
instructions.rs

1//! Contains helpers to build instructions for debugger use
2pub(crate) mod aarch32 {
3    /// Build a MOV instruction
4    pub(crate) fn build_mov(rd: u16, rm: u16) -> u32 {
5        let mut ret = 0b1110_0001_1010_0000_0000_0000_0000_0000;
6
7        ret |= (rd as u32) << 12;
8        ret |= rm as u32;
9
10        ret
11    }
12
13    /// Build a MCR instruction
14    pub(crate) fn build_mcr(
15        coproc: u8,
16        opcode1: u8,
17        reg: u16,
18        ctrl_reg_n: u8,
19        ctrl_reg_m: u8,
20        opcode2: u8,
21    ) -> u32 {
22        let mut ret = 0b1110_1110_0000_0000_0000_0000_0001_0000;
23
24        ret |= (coproc as u32) << 8;
25        ret |= (opcode1 as u32) << 21;
26        ret |= (reg as u32) << 12;
27        ret |= (ctrl_reg_n as u32) << 16;
28        ret |= ctrl_reg_m as u32;
29        ret |= (opcode2 as u32) << 5;
30
31        ret
32    }
33
34    pub(crate) fn build_mrc(
35        coproc: u8,
36        opcode1: u8,
37        reg: u16,
38        ctrl_reg_n: u8,
39        ctrl_reg_m: u8,
40        opcode2: u8,
41    ) -> u32 {
42        let mut ret = 0b1110_1110_0001_0000_0000_0000_0001_0000;
43
44        ret |= (coproc as u32) << 8;
45        ret |= (opcode1 as u32) << 21;
46        ret |= (reg as u32) << 12;
47        ret |= (ctrl_reg_n as u32) << 16;
48        ret |= ctrl_reg_m as u32;
49        ret |= (opcode2 as u32) << 5;
50
51        ret
52    }
53
54    pub(crate) fn build_ldc(coproc: u8, ctrl_reg: u8, reg: u16, imm: u8) -> u32 {
55        let mut ret = 0b1110_1100_1011_0000_0000_0000_0000_0000;
56
57        ret |= (reg as u32) << 16;
58        ret |= (ctrl_reg as u32) << 12;
59        ret |= (coproc as u32) << 8;
60        ret |= (imm as u32) >> 2;
61
62        ret
63    }
64
65    pub(crate) fn build_stc(coproc: u8, ctrl_reg: u8, reg: u16, imm: u8) -> u32 {
66        let mut ret = 0b1110_1100_1010_0000_0000_0000_0000_0000;
67
68        ret |= (reg as u32) << 16;
69        ret |= (ctrl_reg as u32) << 12;
70        ret |= (coproc as u32) << 8;
71        ret |= (imm as u32) >> 2;
72
73        ret
74    }
75
76    /// Read the CPSR
77    pub(crate) fn build_mrs(reg: u16) -> u32 {
78        let mut ret = 0b1110_0001_0000_1111_0000_0000_0000_0000;
79
80        ret |= (reg as u32) << 12;
81
82        ret
83    }
84
85    /// Set all bits of the CPSR
86    pub(crate) fn build_msr(reg: u16) -> u32 {
87        let mut ret = 0b1110_0001_0010_1111_1111_0000_0000_0000;
88
89        ret |= reg as u32;
90
91        ret
92    }
93
94    pub(crate) fn build_vmrs(reg_target: u16, ctrl_reg: u8) -> u32 {
95        let mut ret = 0b1110_1110_1111_0000_0000_1010_0001_0000;
96
97        ret |= (reg_target as u32) << 12;
98        ret |= (ctrl_reg as u32) << 16;
99
100        ret
101    }
102
103    pub(crate) fn build_vmov(op: u8, reg1: u16, reg2: u16, vreg: u16) -> u32 {
104        let mut ret = 0b1110_1100_0100_0000_0000_1011_0001_0000;
105
106        ret |= (op as u32) << 20;
107        ret |= (reg2 as u32) << 16;
108        ret |= (reg1 as u32) << 12;
109        ret |= vreg as u32;
110
111        ret
112    }
113
114    #[cfg(test)]
115    mod tests {
116        use super::*;
117
118        #[test]
119        fn gen_mcr_instruction() {
120            let instr = build_mcr(14, 0, 2, 1, 2, 3);
121
122            // MCR p14, 0, r2, c1, c2, 3
123            assert_eq!(0xEE012E72, instr);
124        }
125
126        #[test]
127        fn gen_mrc_instruction() {
128            let instr = build_mrc(14, 0, 2, 1, 2, 3);
129
130            // MRC p14, 0, r2, c1, c2, 3
131            assert_eq!(0xEE112E72, instr);
132        }
133
134        #[test]
135        fn gen_mov_instruction() {
136            let instr = build_mov(2, 15);
137
138            // MOV r2, pc
139            assert_eq!(0xE1A0200F, instr);
140        }
141
142        #[test]
143        fn gen_ldc_instruction() {
144            let instr = build_ldc(14, 5, 2, 4);
145
146            // LDC p14, c5, [r2], #4
147            assert_eq!(0xECB25E01, instr);
148        }
149
150        #[test]
151        fn gen_stc_instruction() {
152            let instr = build_stc(14, 5, 2, 4);
153
154            // STC p14, c5, [r2], #4
155            assert_eq!(0xECA25E01, instr);
156        }
157
158        #[test]
159        fn gen_mrs_instruction() {
160            let instr = build_mrs(2);
161
162            // MRS r2, CPSR
163            assert_eq!(0xE10F2000, instr);
164        }
165
166        #[test]
167        fn gen_msr_instruction() {
168            let instr = build_msr(2);
169
170            // MSR CPSR_FSXC, r0
171            assert_eq!(0xE12FF002, instr);
172        }
173
174        #[test]
175        fn gen_vmrs_instruction() {
176            let instr = build_vmrs(2, 0b0111);
177
178            // VMRS r2, MVFR0
179            assert_eq!(0xEEF72A10, instr);
180        }
181
182        #[test]
183        fn gen_vmov_instruction() {
184            let instr = build_vmov(1, 1, 2, 3);
185
186            // VMOV r1, r2, d3
187            assert_eq!(0xEC521B13, instr);
188        }
189    }
190}
191
192pub(crate) mod thumb2 {
193    // These are the same encoding in thumb2
194    pub(crate) use super::aarch32::{build_mcr, build_mrc, build_vmov, build_vmrs};
195
196    pub(crate) fn build_ldr(reg_target: u16, reg_source: u16, imm: u8) -> u32 {
197        let mut ret = 0b1111_1000_0101_0000_0000_1011_0000_0000;
198
199        ret |= (reg_source as u32) << 16;
200        ret |= (reg_target as u32) << 12;
201        ret |= imm as u32;
202
203        ret
204    }
205
206    pub(crate) fn build_str(reg_target: u16, reg_source: u16, imm: u8) -> u32 {
207        let mut ret = 0b1111_1000_0100_0000_0000_1011_0000_0000;
208
209        ret |= (reg_source as u32) << 16;
210        ret |= (reg_target as u32) << 12;
211        ret |= imm as u32;
212
213        ret
214    }
215
216    #[cfg(test)]
217    mod tests {
218        use super::*;
219
220        #[test]
221        fn gen_ldr_instruction() {
222            let instr = build_ldr(2, 3, 4);
223
224            // LDR r2, [r3], #4
225            assert_eq!(0xF8532B04, instr);
226        }
227
228        #[test]
229        fn gen_str_instruction() {
230            let instr = build_str(2, 3, 4);
231
232            // STR r2, [r3], #4
233            assert_eq!(0xF8432B04, instr);
234        }
235    }
236}
237
238pub(crate) mod aarch64 {
239    pub(crate) fn build_ldr(reg_target: u16, reg_source: u16, imm: u16) -> u32 {
240        let mut ret = 0b1111_1000_0100_0000_0000_0100_0000_0000;
241
242        ret |= (imm as u32) << 12;
243        ret |= (reg_source as u32) << 5;
244        ret |= reg_target as u32;
245
246        ret
247    }
248
249    pub(crate) fn build_ldrw(reg_target: u16, reg_source: u16, imm: u16) -> u32 {
250        let mut ret = 0b1011_1000_0100_0000_0000_0100_0000_0000;
251
252        ret |= (imm as u32) << 12;
253        ret |= (reg_source as u32) << 5;
254        ret |= reg_target as u32;
255
256        ret
257    }
258
259    pub(crate) fn build_ldrb(reg_target: u16, reg_source: u16, imm: u16) -> u32 {
260        let mut ret = 0b0011_1000_0100_0000_0000_0100_0000_0000;
261
262        ret |= (imm as u32) << 12;
263        ret |= (reg_source as u32) << 5;
264        ret |= reg_target as u32;
265
266        ret
267    }
268
269    pub(crate) fn build_mrs(op0: u8, op1: u8, crn: u8, crm: u8, op2: u8, reg: u16) -> u32 {
270        let mut ret = 0b1101_0101_0011_0000_0000_0000_0000_0000;
271
272        ret |= (op0 as u32) << 19;
273        ret |= (op1 as u32) << 16;
274        ret |= (crn as u32) << 12;
275        ret |= (crm as u32) << 8;
276        ret |= (op2 as u32) << 5;
277        ret |= reg as u32;
278
279        ret
280    }
281
282    pub(crate) fn build_msr(op0: u8, op1: u8, crn: u8, crm: u8, op2: u8, reg: u16) -> u32 {
283        let mut ret = 0b1101_0101_0001_0000_0000_0000_0000_0000;
284
285        ret |= (op0 as u32) << 19;
286        ret |= (op1 as u32) << 16;
287        ret |= (crn as u32) << 12;
288        ret |= (crm as u32) << 8;
289        ret |= (op2 as u32) << 5;
290        ret |= reg as u32;
291
292        ret
293    }
294
295    pub(crate) fn build_str(reg_target: u16, reg_source: u16, imm: u16) -> u32 {
296        let mut ret = 0b1111_1000_0000_0000_0000_0100_0000_0000;
297
298        ret |= (imm as u32) << 12;
299        ret |= (reg_source as u32) << 5;
300        ret |= reg_target as u32;
301
302        ret
303    }
304
305    pub(crate) fn build_strw(reg_target: u16, reg_source: u16, imm: u16) -> u32 {
306        let mut ret = 0b1011_1000_0000_0000_0000_0100_0000_0000;
307
308        ret |= (imm as u32) << 12;
309        ret |= (reg_source as u32) << 5;
310        ret |= reg_target as u32;
311
312        ret
313    }
314
315    pub(crate) fn build_strb(reg_target: u16, reg_source: u16, imm: u16) -> u32 {
316        let mut ret = 0b0011_1000_0000_0000_0000_0100_0000_0000;
317
318        ret |= (imm as u32) << 12;
319        ret |= (reg_source as u32) << 5;
320        ret |= reg_target as u32;
321
322        ret
323    }
324
325    pub(crate) fn build_ins_fp_to_gp(reg_target: u16, reg_source: u16, index: u16) -> u32 {
326        let mut ret = 0b0100_1110_0000_1000_0011_1100_0000_0000;
327
328        ret |= (index as u32) << 20;
329        ret |= (reg_source as u32) << 5;
330        ret |= reg_target as u32;
331
332        ret
333    }
334
335    pub(crate) fn build_ins_gp_to_fp(reg_target: u16, reg_source: u16, index: u16) -> u32 {
336        let mut ret = 0b0100_1110_0000_1000_0001_1100_0000_0000;
337
338        ret |= (index as u32) << 20;
339        ret |= (reg_source as u32) << 5;
340        ret |= reg_target as u32;
341
342        ret
343    }
344
345    #[cfg(test)]
346    mod tests {
347        use super::*;
348        #[test]
349        fn gen_ldr_instruction() {
350            let instr = build_ldr(2, 3, 4);
351
352            // LDR x2, [x3], #4
353            assert_eq!(0xF8404462, instr);
354        }
355
356        #[test]
357        fn gen_ldrw_instruction() {
358            let instr = build_ldrw(2, 3, 4);
359
360            // LDR w2, [x3], #4
361            assert_eq!(0xB8404462, instr);
362        }
363
364        #[test]
365        fn gen_msr_instruction() {
366            let instr = build_msr(2, 3, 4, 1, 2, 3);
367
368            // MSR x3, s3_3_c4_c1_2
369            assert_eq!(0xD5134143, instr);
370        }
371
372        #[test]
373        fn gen_mrs_instruction() {
374            let instr = build_mrs(2, 3, 4, 1, 2, 3);
375
376            // MRS x3, s3_3_c4_c1_2
377            assert_eq!(0xD5334143, instr);
378        }
379
380        #[test]
381        fn gen_str_instruction() {
382            let instr = build_str(2, 3, 4);
383
384            // STR x2, [x3], #4
385            assert_eq!(0xF8004462, instr);
386        }
387
388        #[test]
389        fn gen_strw_instruction() {
390            let instr = build_strw(2, 3, 4);
391
392            // STR w2, [x3], #4
393            assert_eq!(0xB8004462, instr);
394        }
395
396        #[test]
397        fn gen_ins_gp_to_fp_instruction() {
398            let instr = build_ins_gp_to_fp(3, 2, 1);
399
400            // INS v3.d[1], x2
401            assert_eq!(0x4E181C43, instr);
402        }
403
404        #[test]
405        fn gen_ins_fp_to_gp_instruction() {
406            let instr = build_ins_fp_to_gp(3, 2, 1);
407
408            // MOV x3, v2.d[1]
409            assert_eq!(0x4E183C43, instr);
410        }
411    }
412}